Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2025, The Board of Trustees of the University of Illinois,
2 : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
3 : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
4 : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
5 : // contributors. All rights reserved.
6 : //
7 : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
8 : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
9 : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
10 : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
11 : // derivative works, and perform publicly and display publicly, and to permit others to do so.
12 : //
13 : // Redistribution and use in source and binary forms, with or without modification, are permitted
14 : // provided that the following conditions are met:
15 : //
16 : // (1) Redistributions of source code must retain the above copyright notice, this list of
17 : // conditions and the following disclaimer.
18 : //
19 : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
20 : // conditions and the following disclaimer in the documentation and/or other materials
21 : // provided with the distribution.
22 : //
23 : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
24 : // the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
25 : // used to endorse or promote products derived from this software without specific prior
26 : // written permission.
27 : //
28 : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
29 : // without changes from the version obtained under this License, or (ii) Licensee makes a
30 : // reference solely to the software portion of its product, Licensee must refer to the
31 : // software as "EnergyPlus version X" software, where "X" is the version number Licensee
32 : // obtained under this License and may not use a different name for the software. Except as
33 : // specifically required in this Section (4), Licensee shall not use in a company name, a
34 : // product name, in advertising, publicity, or other promotional activities any name, trade
35 : // name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
36 : // similar designation, without the U.S. Department of Energy's prior written consent.
37 : //
38 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
39 : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
40 : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
41 : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43 : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
45 : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46 : // POSSIBILITY OF SUCH DAMAGE.
47 :
48 : // C++ Headers
49 : #include <cmath>
50 :
51 : // ObjexxFCL Headers
52 : #include <ObjexxFCL/Array.functions.hh>
53 : #include <ObjexxFCL/Fmath.hh>
54 :
55 : // EnergyPlus Headers
56 : #include <EnergyPlus/BranchNodeConnections.hh>
57 : #include <EnergyPlus/CurveManager.hh>
58 : #include <EnergyPlus/DXCoils.hh>
59 : #include <EnergyPlus/Data/EnergyPlusData.hh>
60 : #include <EnergyPlus/DataHVACGlobals.hh>
61 : #include <EnergyPlus/DataLoopNode.hh>
62 : #include <EnergyPlus/DataSizing.hh>
63 : #include <EnergyPlus/DesiccantDehumidifiers.hh>
64 : #include <EnergyPlus/EMSManager.hh>
65 : #include <EnergyPlus/Fans.hh>
66 : #include <EnergyPlus/FluidProperties.hh>
67 : #include <EnergyPlus/General.hh>
68 : #include <EnergyPlus/GeneralRoutines.hh>
69 : #include <EnergyPlus/GlobalNames.hh>
70 : #include <EnergyPlus/HeatRecovery.hh>
71 : #include <EnergyPlus/HeatingCoils.hh>
72 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
73 : #include <EnergyPlus/NodeInputManager.hh>
74 : #include <EnergyPlus/OutAirNodeManager.hh>
75 : #include <EnergyPlus/OutputProcessor.hh>
76 : #include <EnergyPlus/PlantUtilities.hh>
77 : #include <EnergyPlus/Psychrometrics.hh>
78 : #include <EnergyPlus/ScheduleManager.hh>
79 : #include <EnergyPlus/SteamCoils.hh>
80 : #include <EnergyPlus/UtilityRoutines.hh>
81 : #include <EnergyPlus/VariableSpeedCoils.hh>
82 : #include <EnergyPlus/WaterCoils.hh>
83 :
84 : namespace EnergyPlus {
85 :
86 : namespace DesiccantDehumidifiers {
87 :
88 : // Module containing the routines dealing with dehumidifiers
89 :
90 : // MODULE INFORMATION:
91 : // AUTHOR Michael J. Witte, GARD Analytics, Inc.
92 : // for Gas Research Institute
93 : // DATE WRITTEN March 2001
94 : // MODIFIED Jan 2005 M. J. Witte, GARD Analytics, Inc.
95 : // Add new control type option:
96 : // NODE LEAVING HUMRAT SETPOINT:BYPASS
97 : // Change existing control type to:
98 : // FIXED LEAVING HUMRAT SETPOINT:BYPASS
99 : // Work supported by ASHRAE research project 1254-RP
100 : // June 2007 R. Raustad, FSEC
101 : // Added new dehumidifier type -- DESICCANT DEHUMIDIFIER
102 : // Jan 2012 B. Nigusse, FSEC
103 : // Added steam and hot water heating coils
104 :
105 : // RE-ENGINEERED na
106 :
107 : // PURPOSE OF THIS MODULE:
108 : // To encapsulate the data and routines required to model desiccant dehumidifier
109 : // components in the EnergyPlus HVAC simulation
110 :
111 : // METHODOLOGY EMPLOYED:
112 : // The desiccant dehumidifier emcompasses not just the component but also its
113 : // control. The desiccant dehumidifier removes moisture from its air inlet to meet
114 : // the HumRatMax setpoint at its exit node. The HumRatMax is set by
115 : // an external setpoint manager or is a fixed user input.
116 :
117 : // REFERENCES: na
118 :
119 : // OTHER NOTES: This module is based substantially on the Humidifiers module.
120 : // authored by Fred Buhl.
121 : // Development of portions of this module was funded by the Gas Research Institute.
122 : // (Please see copyright and disclaimer information at end of module)
123 :
124 : Real64 constexpr TempSteamIn = 100.0;
125 :
126 283978 : void SimDesiccantDehumidifier(EnergyPlusData &state,
127 : std::string const &CompName, // name of the dehumidifier unit
128 : bool const FirstHVACIteration, // TRUE if 1st HVAC simulation of system timestep
129 : int &CompIndex)
130 : {
131 :
132 : // SUBROUTINE INFORMATION:
133 : // AUTHOR Michael J. Witte, GARD Analytics, Inc.
134 : // for Gas Research Institute
135 : // DATE WRITTEN March 2001
136 : // MODIFIED June 2007, R. Raustad, Added new dehumidifier type -- DESICCANT DEHUMIDIFIER
137 :
138 : // PURPOSE OF THIS SUBROUTINE:
139 : // Manage the simulation of an air dehumidifier
140 :
141 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
142 : int DesicDehumNum; // index of solid desiccant unit being simulated
143 : Real64 HumRatNeeded; // process air leaving humidity ratio set by controller [kg water/kg air]
144 :
145 283978 : if (state.dataDesiccantDehumidifiers->GetInputDesiccantDehumidifier) {
146 7 : GetDesiccantDehumidifierInput(state);
147 7 : state.dataDesiccantDehumidifiers->GetInputDesiccantDehumidifier = false;
148 : }
149 :
150 : // Get the desiccant dehumidifier unit index
151 283978 : if (CompIndex == 0) {
152 9 : DesicDehumNum = Util::FindItemInList(CompName, state.dataDesiccantDehumidifiers->DesicDehum);
153 9 : if (DesicDehumNum == 0) {
154 0 : ShowFatalError(state, format("SimDesiccantDehumidifier: Unit not found={}", CompName));
155 : }
156 9 : CompIndex = DesicDehumNum;
157 : } else {
158 283969 : DesicDehumNum = CompIndex;
159 283969 : if (DesicDehumNum > state.dataDesiccantDehumidifiers->NumDesicDehums || DesicDehumNum < 1) {
160 0 : ShowFatalError(state,
161 0 : format("SimDesiccantDehumidifier: Invalid CompIndex passed={}, Number of Units={}, Entered Unit name={}",
162 : DesicDehumNum,
163 0 : state.dataDesiccantDehumidifiers->NumDesicDehums,
164 : CompName));
165 : }
166 283969 : if (CompName != state.dataDesiccantDehumidifiers->DesicDehum(DesicDehumNum).Name) {
167 0 : ShowFatalError(state,
168 0 : format("SimDesiccantDehumidifier: Invalid CompIndex passed={}, Unit name={}, stored Unit Name for that index={}",
169 : DesicDehumNum,
170 : CompName,
171 0 : state.dataDesiccantDehumidifiers->DesicDehum(DesicDehumNum).Name));
172 : }
173 : }
174 :
175 283978 : InitDesiccantDehumidifier(state, DesicDehumNum, FirstHVACIteration);
176 :
177 283978 : ControlDesiccantDehumidifier(state, DesicDehumNum, HumRatNeeded, FirstHVACIteration);
178 :
179 : // call the correct dehumidifier calculation routine
180 283978 : switch (state.dataDesiccantDehumidifiers->DesicDehum(DesicDehumNum).DehumTypeCode) {
181 92320 : case DesicDehumType::Solid: {
182 92320 : CalcSolidDesiccantDehumidifier(state, DesicDehumNum, HumRatNeeded, FirstHVACIteration);
183 92320 : } break;
184 191658 : case DesicDehumType::Generic: {
185 191658 : CalcGenericDesiccantDehumidifier(state, DesicDehumNum, HumRatNeeded, FirstHVACIteration);
186 191658 : } break;
187 0 : default: {
188 0 : ShowFatalError(state,
189 0 : format("Invalid type, Desiccant Dehumidifer={}", state.dataDesiccantDehumidifiers->DesicDehum(DesicDehumNum).DehumType));
190 0 : } break;
191 : }
192 :
193 283978 : UpdateDesiccantDehumidifier(state, DesicDehumNum);
194 :
195 283978 : ReportDesiccantDehumidifier(state, DesicDehumNum);
196 283978 : }
197 :
198 7 : void GetDesiccantDehumidifierInput(EnergyPlusData &state)
199 : {
200 :
201 : // SUBROUTINE INFORMATION:
202 : // AUTHOR Michael J. Witte, GARD Analytics, Inc.
203 : // for Gas Research Institute
204 : // DATE WRITTEN March 2001
205 : // MODIFIED Jan 2005 M. J. Witte, GARD Analytics, Inc.
206 : // Add new control type option:
207 : // NODE LEAVING HUMRAT SETPOINT:BYPASS
208 : // Change existing control type to:
209 : // FIXED LEAVING HUMRAT SETPOINT:BYPASS
210 : // Work supported by ASHRAE research project 1254-RP
211 : // June 2007 R. Raustad, FSEC
212 : // Added new dehumidifier type -- DESICCANT DEHUMIDIFIER
213 :
214 : // PURPOSE OF THIS SUBROUTINE:
215 : // Obtains input data for humidifiers and stores it in dehumidifier data structures.
216 :
217 : // METHODOLOGY EMPLOYED:
218 : // Uses InputProcessor "Get" routines to obtain data.
219 :
220 : // SUBROUTINE PARAMETER DEFINITIONS:
221 : static constexpr std::string_view RoutineName("GetDesiccantDehumidifierInput: "); // include trailing blank space
222 : static constexpr std::string_view routineName = "GetDesiccantDehumidifierInput";
223 21 : static std::string const dehumidifierDesiccantNoFans("Dehumidifier:Desiccant:NoFans");
224 :
225 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
226 : int NumAlphas; // Number of Alphas for each GetObjectItem call
227 : int NumNumbers; // Number of Numbers for each GetObjectItem call
228 : int IOStatus; // Used in GetObjectItem
229 7 : bool ErrorsFound(false); // Set to true if errors in input, fatal at end of routine
230 7 : bool ErrorsFound2(false); // Set to true if errors in input, fatal at end of routine
231 7 : bool ErrorsFoundGeneric(false); // Set to true if errors in input, fatal at end of routine
232 : bool IsNotOK; // Flag to verify name
233 : bool OANodeError; // Flag for check on outside air node
234 7 : std::string RegenCoilInlet; // Desiccant system regeneration air heater inlet node
235 7 : std::string RegenCoilOutlet; // Desiccant system regeneration air heater outlet node
236 : int DesuperHeaterIndex; // Index of desuperheater heating coil
237 : int RegenCoilControlNodeNum; // Control node number of regen heating coil
238 : Real64 CoilBypassedFlowFrac; // Bypass air fraction for multimode DX coils
239 7 : Array1D_string Alphas; // Alpha input items for object
240 7 : Array1D_string cAlphaFields; // Alpha field names
241 7 : Array1D_string cNumericFields; // Numeric field names
242 7 : Array1D<Real64> Numbers; // Numeric input items for object
243 7 : Array1D_bool lAlphaBlanks; // Logical array, alpha field input BLANK = .TRUE.
244 7 : Array1D_bool lNumericBlanks; // Logical array, numeric field input BLANK = .TRUE.
245 : bool errFlag; // local error flag
246 7 : std::string RegenCoilType; // Regen heating coil type
247 7 : std::string RegenCoilName; // Regen heating coil name
248 : bool RegairHeatingCoilFlag; // local error flag
249 :
250 7 : int TotalArgs = 0;
251 :
252 14 : state.dataDesiccantDehumidifiers->NumSolidDesicDehums =
253 7 : state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, dehumidifierDesiccantNoFans);
254 14 : state.dataDesiccantDehumidifiers->NumGenericDesicDehums =
255 7 : state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "Dehumidifier:Desiccant:System");
256 14 : state.dataDesiccantDehumidifiers->NumDesicDehums =
257 7 : state.dataDesiccantDehumidifiers->NumSolidDesicDehums + state.dataDesiccantDehumidifiers->NumGenericDesicDehums;
258 : // allocate the data array
259 7 : state.dataDesiccantDehumidifiers->DesicDehum.allocate(state.dataDesiccantDehumidifiers->NumDesicDehums);
260 7 : state.dataDesiccantDehumidifiers->UniqueDesicDehumNames.reserve(state.dataDesiccantDehumidifiers->NumDesicDehums);
261 7 : state.dataDesiccantDehumidifiers->GetInputDesiccantDehumidifier = false;
262 :
263 7 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, dehumidifierDesiccantNoFans, TotalArgs, NumAlphas, NumNumbers);
264 7 : int MaxNums = NumNumbers;
265 7 : int MaxAlphas = NumAlphas;
266 7 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, "Dehumidifier:Desiccant:System", TotalArgs, NumAlphas, NumNumbers);
267 7 : MaxNums = max(MaxNums, NumNumbers);
268 7 : MaxAlphas = max(MaxAlphas, NumAlphas);
269 :
270 7 : Alphas.allocate(MaxAlphas);
271 7 : cAlphaFields.allocate(MaxAlphas);
272 7 : cNumericFields.allocate(MaxNums);
273 7 : Numbers.dimension(MaxNums, 0.0);
274 7 : lAlphaBlanks.dimension(MaxAlphas, true);
275 7 : lNumericBlanks.dimension(MaxNums, true);
276 :
277 : // loop over solid desiccant dehumidifiers and load the input data
278 7 : std::string CurrentModuleObject = dehumidifierDesiccantNoFans;
279 12 : for (int DesicDehumIndex = 1; DesicDehumIndex <= state.dataDesiccantDehumidifiers->NumSolidDesicDehums; ++DesicDehumIndex) {
280 5 : auto &desicDehum = state.dataDesiccantDehumidifiers->DesicDehum(DesicDehumIndex);
281 :
282 5 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
283 : CurrentModuleObject,
284 : DesicDehumIndex,
285 : Alphas,
286 : NumAlphas,
287 : Numbers,
288 : NumNumbers,
289 : IOStatus,
290 : lNumericBlanks,
291 : lAlphaBlanks,
292 : cAlphaFields,
293 : cNumericFields);
294 :
295 5 : ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
296 :
297 5 : GlobalNames::VerifyUniqueInterObjectName(
298 10 : state, state.dataDesiccantDehumidifiers->UniqueDesicDehumNames, Alphas(1), CurrentModuleObject, cAlphaFields(1), ErrorsFound);
299 5 : desicDehum.Name = Alphas(1);
300 5 : desicDehum.DehumType = CurrentModuleObject;
301 5 : desicDehum.DehumTypeCode = DesicDehumType::Solid;
302 5 : desicDehum.Sched = Alphas(2);
303 :
304 5 : if (lAlphaBlanks(2)) {
305 0 : desicDehum.availSched = Sched::GetScheduleAlwaysOn(state);
306 5 : } else if ((desicDehum.availSched = Sched::GetSchedule(state, Alphas(2))) == nullptr) {
307 0 : ShowSevereItemNotFound(state, eoh, cAlphaFields(2), Alphas(2));
308 0 : ErrorsFound = true;
309 : }
310 : // For node connections, this object is both a parent and a non-parent, because the
311 : // Desiccant wheel is not called out as a separate component, its nodes must be connected
312 : // as ObjectIsNotParent. But for the Regen fan, the nodes are connected as ObjectIsParent
313 5 : desicDehum.ProcAirInNode = NodeInputManager::GetOnlySingleNode(state,
314 5 : Alphas(3),
315 : ErrorsFound,
316 : DataLoopNode::ConnectionObjectType::DehumidifierDesiccantNoFans,
317 5 : Alphas(1),
318 : DataLoopNode::NodeFluidType::Air,
319 : DataLoopNode::ConnectionType::Inlet,
320 : NodeInputManager::CompFluidStream::Primary,
321 : DataLoopNode::ObjectIsNotParent);
322 :
323 5 : desicDehum.ProcAirOutNode = NodeInputManager::GetOnlySingleNode(state,
324 5 : Alphas(4),
325 : ErrorsFound,
326 : DataLoopNode::ConnectionObjectType::DehumidifierDesiccantNoFans,
327 5 : Alphas(1),
328 : DataLoopNode::NodeFluidType::Air,
329 : DataLoopNode::ConnectionType::Outlet,
330 : NodeInputManager::CompFluidStream::Primary,
331 : DataLoopNode::ObjectIsNotParent);
332 :
333 5 : desicDehum.RegenAirInNode = NodeInputManager::GetOnlySingleNode(state,
334 5 : Alphas(5),
335 : ErrorsFound,
336 : DataLoopNode::ConnectionObjectType::DehumidifierDesiccantNoFans,
337 5 : Alphas(1),
338 : DataLoopNode::NodeFluidType::Air,
339 : DataLoopNode::ConnectionType::Inlet,
340 : NodeInputManager::CompFluidStream::Secondary,
341 : DataLoopNode::ObjectIsNotParent);
342 :
343 5 : desicDehum.RegenFanInNode = NodeInputManager::GetOnlySingleNode(state,
344 5 : Alphas(6),
345 : ErrorsFound,
346 : DataLoopNode::ConnectionObjectType::DehumidifierDesiccantNoFans,
347 5 : Alphas(1),
348 : DataLoopNode::NodeFluidType::Air,
349 : DataLoopNode::ConnectionType::Internal,
350 : NodeInputManager::CompFluidStream::Secondary,
351 : DataLoopNode::ObjectIsParent);
352 :
353 5 : if (Util::SameString(Alphas(7), "LEAVING HUMRAT:BYPASS")) {
354 0 : ShowWarningError(state, format("{}{} = {}", RoutineName, CurrentModuleObject, desicDehum.Name));
355 0 : ShowContinueError(state, format("Obsolete {} = {}", cAlphaFields(7), Alphas(7)));
356 0 : ShowContinueError(state, "setting to LeavingMaximumHumidityRatioSetpoint");
357 0 : desicDehum.controlType = DesicDehumCtrlType::FixedHumratBypass;
358 : }
359 5 : if (Util::SameString(Alphas(7), "LeavingMaximumHumidityRatioSetpoint")) {
360 3 : desicDehum.controlType = DesicDehumCtrlType::FixedHumratBypass;
361 : }
362 5 : if (Util::SameString(Alphas(7), "SystemNodeMaximumHumidityRatioSetpoint")) {
363 2 : desicDehum.controlType = DesicDehumCtrlType::NodeHumratBypass;
364 : }
365 5 : if (desicDehum.controlType == DesicDehumCtrlType::Invalid) {
366 0 : ShowWarningError(state, format("{}{} = {}", RoutineName, CurrentModuleObject, desicDehum.Name));
367 0 : ShowContinueError(state, format("Invalid {} = {}", cAlphaFields(7), Alphas(7)));
368 0 : ShowContinueError(state, "setting to LeavingMaximumHumidityRatioSetpoint");
369 0 : desicDehum.controlType = DesicDehumCtrlType::FixedHumratBypass;
370 : }
371 5 : desicDehum.HumRatSet = Numbers(1);
372 5 : desicDehum.NomProcAirVolFlow = Numbers(2);
373 5 : desicDehum.NomProcAirVel = Numbers(3);
374 :
375 5 : desicDehum.RegenCoilType = Alphas(8);
376 5 : desicDehum.RegenCoilName = Alphas(9);
377 :
378 5 : desicDehum.regenFanType = static_cast<HVAC::FanType>(getEnumValue(HVAC::fanTypeNamesUC, Alphas(10)));
379 5 : assert(desicDehum.regenFanType != HVAC::FanType::Invalid);
380 :
381 5 : RegenCoilType = Alphas(8);
382 5 : RegenCoilName = Alphas(9);
383 :
384 10 : if (Util::SameString(desicDehum.RegenCoilType, "Coil:Heating:Electric") ||
385 10 : Util::SameString(desicDehum.RegenCoilType, "Coil:Heating:Fuel")) {
386 5 : if (Util::SameString(desicDehum.RegenCoilType, "Coil:Heating:Electric")) {
387 0 : desicDehum.RegenCoilType_Num = HVAC::Coil_HeatingElectric;
388 : }
389 5 : if (Util::SameString(desicDehum.RegenCoilType, "Coil:Heating:Fuel")) {
390 5 : desicDehum.RegenCoilType_Num = HVAC::Coil_HeatingGasOrOtherFuel;
391 : }
392 5 : ValidateComponent(state, desicDehum.RegenCoilType, desicDehum.RegenCoilName, ErrorsFound2, CurrentModuleObject + '=' + Alphas(1));
393 5 : if (ErrorsFound2) {
394 0 : ErrorsFound = true;
395 : }
396 5 : HeatingCoils::GetCoilIndex(state, desicDehum.RegenCoilName, desicDehum.RegenCoilIndex, ErrorsFound2);
397 5 : if (ErrorsFound2) {
398 0 : ErrorsFound = true;
399 : }
400 :
401 0 : } else if (Util::SameString(desicDehum.RegenCoilType, "Coil:Heating:Water")) {
402 0 : desicDehum.RegenCoilType_Num = HVAC::Coil_HeatingWater;
403 0 : ValidateComponent(state, RegenCoilType, RegenCoilName, IsNotOK, CurrentModuleObject);
404 0 : if (IsNotOK) {
405 0 : ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
406 0 : ErrorsFound = true;
407 : } else { // mine data from heating coil object
408 0 : errFlag = false;
409 0 : desicDehum.RegenCoilIndex = WaterCoils::GetWaterCoilIndex(state, "COIL:HEATING:WATER", RegenCoilName, errFlag);
410 0 : if (desicDehum.RegenCoilIndex == 0) {
411 0 : ShowSevereError(state, format("{}{} illegal {} = {}", RoutineName, CurrentModuleObject, cAlphaFields(9), RegenCoilName));
412 0 : ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, desicDehum.Name));
413 0 : ErrorsFound = true;
414 : }
415 :
416 : // Get the Heating Coil Hot water Inlet or control Node number
417 0 : errFlag = false;
418 0 : desicDehum.CoilControlNode = WaterCoils::GetCoilWaterInletNode(state, "Coil:Heating:Water", RegenCoilName, errFlag);
419 0 : if (errFlag) {
420 0 : ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, desicDehum.Name));
421 0 : ErrorsFound = true;
422 : }
423 :
424 : // Get the Regeneration Heating Coil hot water max volume flow rate
425 0 : errFlag = false;
426 0 : desicDehum.MaxCoilFluidFlow = WaterCoils::GetCoilMaxWaterFlowRate(state, "Coil:Heating:Water", RegenCoilName, errFlag);
427 0 : if (errFlag) {
428 0 : ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, desicDehum.Name));
429 0 : ErrorsFound = true;
430 : }
431 :
432 : // Get the Regeneration Heating Coil Inlet Node
433 0 : errFlag = false;
434 0 : int RegenCoilAirInletNode = WaterCoils::GetCoilInletNode(state, "Coil:Heating:Water", RegenCoilName, errFlag);
435 0 : desicDehum.RegenCoilInletNode = RegenCoilAirInletNode;
436 0 : if (errFlag) {
437 0 : ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, desicDehum.Name));
438 0 : ErrorsFound = true;
439 : }
440 :
441 : // Get the Regeneration Heating Coil Outlet Node
442 0 : errFlag = false;
443 0 : int RegenCoilAirOutletNode = WaterCoils::GetCoilOutletNode(state, "Coil:Heating:Water", RegenCoilName, errFlag);
444 0 : desicDehum.RegenCoilOutletNode = RegenCoilAirOutletNode;
445 0 : if (errFlag) {
446 0 : ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, desicDehum.Name));
447 0 : ErrorsFound = true;
448 : }
449 : }
450 0 : } else if (Util::SameString(desicDehum.RegenCoilType, "Coil:Heating:Steam")) {
451 0 : desicDehum.RegenCoilType_Num = HVAC::Coil_HeatingSteam;
452 0 : ValidateComponent(state, Alphas(8), RegenCoilName, IsNotOK, CurrentModuleObject);
453 0 : if (IsNotOK) {
454 0 : ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
455 0 : ErrorsFound = true;
456 : } else { // mine data from the regeneration heating coil object
457 :
458 0 : errFlag = false;
459 0 : desicDehum.RegenCoilIndex = SteamCoils::GetSteamCoilIndex(state, "COIL:HEATING:STEAM", RegenCoilName, errFlag);
460 0 : if (desicDehum.RegenCoilIndex == 0) {
461 0 : ShowSevereError(state, format("{}{} illegal {} = {}", RoutineName, CurrentModuleObject, cAlphaFields(9), RegenCoilName));
462 0 : ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, desicDehum.Name));
463 0 : ErrorsFound = true;
464 : }
465 :
466 : // Get the regeneration Heating Coil steam inlet node number
467 0 : errFlag = false;
468 0 : desicDehum.CoilControlNode = SteamCoils::GetCoilSteamInletNode(state, "Coil:Heating:Steam", RegenCoilName, errFlag);
469 0 : if (errFlag) {
470 0 : ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, desicDehum.Name));
471 0 : ErrorsFound = true;
472 : }
473 :
474 : // Get the regeneration heating Coil steam max volume flow rate
475 0 : desicDehum.MaxCoilFluidFlow = SteamCoils::GetCoilMaxSteamFlowRate(state, desicDehum.RegenCoilIndex, errFlag);
476 0 : if (desicDehum.MaxCoilFluidFlow > 0.0) {
477 0 : Real64 SteamDensity = Fluid::GetSteam(state)->getSatDensity(state, TempSteamIn, 1.0, dehumidifierDesiccantNoFans);
478 0 : desicDehum.MaxCoilFluidFlow *= SteamDensity;
479 : }
480 :
481 : // Get the regeneration heating Coil Inlet Node
482 0 : errFlag = false;
483 0 : int RegenCoilAirInletNode = SteamCoils::GetCoilAirInletNode(state, desicDehum.RegenCoilIndex, RegenCoilName, errFlag);
484 0 : desicDehum.RegenCoilInletNode = RegenCoilAirInletNode;
485 0 : if (errFlag) {
486 0 : ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, desicDehum.Name));
487 0 : ErrorsFound = true;
488 : }
489 :
490 : // Get the regeneration heating Coil Outlet Node
491 0 : errFlag = false;
492 0 : int RegenCoilAirOutletNode = SteamCoils::GetCoilAirOutletNode(state, desicDehum.RegenCoilIndex, RegenCoilName, errFlag);
493 0 : desicDehum.RegenCoilOutletNode = RegenCoilAirOutletNode;
494 0 : if (errFlag) {
495 0 : ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, desicDehum.Name));
496 0 : ErrorsFound = true;
497 : }
498 : }
499 : } else {
500 0 : ShowSevereError(state, format("{}{} = {}", RoutineName, CurrentModuleObject, Alphas(1)));
501 0 : ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(8), desicDehum.RegenCoilType));
502 0 : ErrorsFound = true;
503 : }
504 :
505 5 : desicDehum.NomRotorPower = Numbers(4);
506 5 : desicDehum.RegenFanName = Alphas(11);
507 :
508 5 : BranchNodeConnections::TestCompSet(state, desicDehum.DehumType, desicDehum.Name, Alphas(3), Alphas(4), "Process Air Nodes");
509 :
510 : // Set up component set for regen coil
511 5 : BranchNodeConnections::SetUpCompSets(state, desicDehum.DehumType, desicDehum.Name, Alphas(8), Alphas(9), "UNDEFINED", "UNDEFINED");
512 :
513 : // Set up component set for regen fan
514 5 : BranchNodeConnections::SetUpCompSets(state, desicDehum.DehumType, desicDehum.Name, Alphas(10), Alphas(11), Alphas(6), "UNDEFINED");
515 :
516 5 : if ((!Util::SameString(Alphas(12), "Default")) && (Util::SameString(Alphas(12), "UserCurves"))) {
517 0 : ShowWarningError(state, format("{}{}: Invalid{} = {}", RoutineName, CurrentModuleObject, cAlphaFields(12), Alphas(12)));
518 0 : ShowContinueError(state, "resetting to Default");
519 0 : desicDehum.PerformanceModel_Num = PerformanceModel::Default;
520 : }
521 :
522 5 : if (Util::SameString(Alphas(12), "UserCurves")) {
523 0 : desicDehum.PerformanceModel_Num = PerformanceModel::UserCurves;
524 0 : desicDehum.ProcDryBulbCurvefTW = Curve::GetCurveIndex(state, Alphas(13));
525 0 : if (desicDehum.ProcDryBulbCurvefTW == 0) {
526 0 : ShowSevereError(state, format("{}Curve object={} not found.", RoutineName, Alphas(13)));
527 0 : ErrorsFound2 = true;
528 : }
529 0 : desicDehum.ProcDryBulbCurvefV = Curve::GetCurveIndex(state, Alphas(14));
530 0 : if (desicDehum.ProcDryBulbCurvefV == 0) {
531 0 : ShowSevereError(state, format("{}Curve object={} not found.", RoutineName, Alphas(14)));
532 0 : ErrorsFound2 = true;
533 : }
534 0 : desicDehum.ProcHumRatCurvefTW = Curve::GetCurveIndex(state, Alphas(15));
535 0 : if (desicDehum.ProcHumRatCurvefTW == 0) {
536 0 : ShowSevereError(state, format("{}Curve object={} not found.", RoutineName, Alphas(15)));
537 0 : ErrorsFound2 = true;
538 : }
539 0 : desicDehum.ProcHumRatCurvefV = Curve::GetCurveIndex(state, Alphas(16));
540 0 : if (desicDehum.ProcHumRatCurvefV == 0) {
541 0 : ShowSevereError(state, format("{}Curve object={} not found.", RoutineName, Alphas(16)));
542 0 : ErrorsFound2 = true;
543 : }
544 0 : desicDehum.RegenEnergyCurvefTW = Curve::GetCurveIndex(state, Alphas(17));
545 0 : if (desicDehum.RegenEnergyCurvefTW == 0) {
546 0 : ShowSevereError(state, format("{}Curve object={} not found.", RoutineName, Alphas(17)));
547 0 : ErrorsFound2 = true;
548 : }
549 0 : desicDehum.RegenEnergyCurvefV = Curve::GetCurveIndex(state, Alphas(18));
550 0 : if (desicDehum.RegenEnergyCurvefV == 0) {
551 0 : ShowSevereError(state, format("{}Curve object={} not found.", RoutineName, Alphas(18)));
552 0 : ErrorsFound2 = true;
553 : }
554 0 : desicDehum.RegenVelCurvefTW = Curve::GetCurveIndex(state, Alphas(19));
555 0 : if (desicDehum.RegenVelCurvefTW == 0) {
556 0 : ShowSevereError(state, format("{}Curve object={} not found.", RoutineName, Alphas(19)));
557 0 : ErrorsFound2 = true;
558 : }
559 0 : desicDehum.RegenVelCurvefV = Curve::GetCurveIndex(state, Alphas(20));
560 0 : if (desicDehum.RegenVelCurvefV == 0) {
561 0 : ShowSevereError(state, format("{}Curve object={} not found.", RoutineName, Alphas(20)));
562 0 : ErrorsFound2 = true;
563 : }
564 0 : if (ErrorsFound2) {
565 0 : ShowSevereError(state, format("{}{} = {}", RoutineName, CurrentModuleObject, Alphas(1)));
566 0 : ShowContinueError(state, "Errors found in getting performance curves.");
567 0 : ErrorsFound = true;
568 : }
569 0 : desicDehum.NomRegenTemp = Numbers(5);
570 :
571 : // Validate regen fan type, for user defined curves, can be constant or variable volume
572 0 : if (desicDehum.regenFanType == HVAC::FanType::Constant || desicDehum.regenFanType == HVAC::FanType::VAV ||
573 0 : desicDehum.regenFanType == HVAC::FanType::SystemModel) {
574 0 : ValidateComponent(state,
575 0 : HVAC::fanTypeNamesUC[(int)desicDehum.regenFanType],
576 0 : desicDehum.RegenFanName,
577 : ErrorsFound2,
578 0 : CurrentModuleObject + " = " + Alphas(1));
579 0 : if (ErrorsFound2) {
580 0 : ErrorsFound = true;
581 : }
582 : } else {
583 0 : ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
584 0 : ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(10), Alphas(10)));
585 0 : ErrorsFound = true;
586 : }
587 : } else {
588 : // If DEFAULT performance model, set operating limits curves. Unit is off outside this range
589 5 : desicDehum.PerformanceModel_Num = PerformanceModel::Default;
590 : // this is wrong to initialize all dehumidifiers, it should be just this specific dehumidifier
591 : // this was likely tested with only 1 desiccant dehumidifier so this was never discovered
592 : // or maybe if there were more than 1 these data would not be used when Alphas(12) == "UserCurves" ???
593 10 : for (auto &e : state.dataDesiccantDehumidifiers->DesicDehum) {
594 5 : e.MinProcAirInTemp = 1.67; // 35 F
595 5 : e.MaxProcAirInTemp = 48.89; // 120 F
596 5 : e.MinProcAirInHumRat = 0.002857; // 20 gr/lb
597 5 : e.MaxProcAirInHumRat = 0.02857; // 200 gr/lb
598 : }
599 : // If DEFAULT performance model, warn if curve names and nominal regen temp have values
600 10 : if ((!lAlphaBlanks(13)) || (!lAlphaBlanks(14)) || (!lAlphaBlanks(15)) || (!lAlphaBlanks(16)) || (!lAlphaBlanks(17)) ||
601 10 : (!lAlphaBlanks(18)) || (!lAlphaBlanks(19)) || (!lAlphaBlanks(20))) {
602 0 : ShowWarningError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
603 0 : ShowContinueError(state, "DEFAULT performance selected, curve names and nominal regen temp will be ignored.");
604 : }
605 5 : if (desicDehum.NomProcAirVel > 4.064) {
606 0 : ShowWarningError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
607 0 : ShowContinueError(state, format("{} > 4.064 m/s.; Value in input={:.3R}", cNumericFields(3), desicDehum.NomProcAirVel));
608 0 : ShowContinueError(state, "DEFAULT performance curves not valid outside 2.032 to 4.064 m/s (400 to 800 fpm).");
609 : }
610 5 : if (desicDehum.NomProcAirVel < 2.032) {
611 0 : ShowWarningError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
612 0 : ShowContinueError(state, format("{} < 2.032 m/s.; Value in input={:.3R}", cNumericFields(3), desicDehum.NomProcAirVel));
613 0 : ShowContinueError(state, "DEFAULT performance curves not valid outside 2.032 to 4.064 m/s (400 to 800 fpm).");
614 : }
615 : // Validate regen fan type, for default curves, can only variable volume
616 5 : if (desicDehum.regenFanType == HVAC::FanType::VAV || desicDehum.regenFanType == HVAC::FanType::SystemModel) {
617 10 : ValidateComponent(state,
618 5 : HVAC::fanTypeNamesUC[(int)desicDehum.regenFanType],
619 5 : desicDehum.RegenFanName,
620 : ErrorsFound2,
621 10 : CurrentModuleObject + " = " + Alphas(1));
622 5 : if (ErrorsFound2) {
623 0 : ErrorsFound = true;
624 : }
625 : } else {
626 0 : ShowSevereError(state, format("{} = {}", CurrentModuleObject, Alphas(1)));
627 0 : ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(10), Alphas(10)));
628 0 : ShowContinueError(state, "For DEFAULT performance model, the regen fan type must be Fan:VariableVolume");
629 0 : ErrorsFound = true;
630 : }
631 : }
632 : // process regen fan
633 5 : ErrorsFound2 = false;
634 :
635 5 : desicDehum.RegenFanIndex = Fans::GetFanIndex(state, desicDehum.RegenFanName);
636 5 : if (desicDehum.RegenFanIndex == 0) {
637 0 : ShowSevereItemNotFound(state, eoh, cAlphaFields(11), desicDehum.RegenFanName);
638 0 : ErrorsFoundGeneric = true;
639 : } else {
640 5 : auto *fan = state.dataFans->fans(desicDehum.RegenFanIndex);
641 5 : assert(desicDehum.regenFanType == fan->type);
642 5 : desicDehum.RegenFanInNode = fan->inletNodeNum;
643 5 : desicDehum.RegenFanOutNode = fan->outletNodeNum;
644 : }
645 : }
646 :
647 11 : for (int DesicDehumIndex = 1; DesicDehumIndex <= state.dataDesiccantDehumidifiers->NumGenericDesicDehums; ++DesicDehumIndex) {
648 :
649 4 : CurrentModuleObject = "Dehumidifier:Desiccant:System";
650 :
651 4 : int DesicDehumNum = DesicDehumIndex + state.dataDesiccantDehumidifiers->NumSolidDesicDehums;
652 4 : auto &desicDehum = state.dataDesiccantDehumidifiers->DesicDehum(DesicDehumNum);
653 :
654 4 : desicDehum.DehumType = CurrentModuleObject;
655 4 : desicDehum.DehumTypeCode = DesicDehumType::Generic;
656 4 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
657 : desicDehum.DehumType,
658 : DesicDehumIndex,
659 : Alphas,
660 : NumAlphas,
661 : Numbers,
662 : NumNumbers,
663 : IOStatus,
664 : lNumericBlanks,
665 : lAlphaBlanks,
666 : cAlphaFields,
667 : cNumericFields);
668 :
669 4 : ErrorObjectHeader eoh{routineName, desicDehum.DehumType, Alphas(1)};
670 :
671 4 : GlobalNames::VerifyUniqueInterObjectName(
672 8 : state, state.dataDesiccantDehumidifiers->UniqueDesicDehumNames, Alphas(1), CurrentModuleObject, cAlphaFields(1), ErrorsFoundGeneric);
673 4 : desicDehum.Name = Alphas(1);
674 :
675 4 : ErrorsFound2 = false;
676 4 : ValidateComponent(state, desicDehum.DehumType, desicDehum.Name, ErrorsFound2, desicDehum.DehumType + " = \"" + desicDehum.Name + "\"");
677 4 : if (ErrorsFound2) {
678 0 : ShowSevereError(state, format("{} \"{}\" is not unique", desicDehum.DehumType, desicDehum.Name));
679 0 : ErrorsFoundGeneric = true;
680 : }
681 :
682 4 : desicDehum.Sched = Alphas(2);
683 4 : if (lAlphaBlanks(2)) {
684 0 : desicDehum.availSched = Sched::GetScheduleAlwaysOn(state);
685 4 : } else if ((desicDehum.availSched = Sched::GetSchedule(state, Alphas(2))) == nullptr) {
686 0 : ShowSevereItemNotFound(state, eoh, cAlphaFields(2), Alphas(2));
687 0 : ErrorsFound = true;
688 : }
689 :
690 4 : desicDehum.HXType = Alphas(3);
691 4 : desicDehum.HXName = Alphas(4);
692 :
693 4 : if (!Util::SameString(desicDehum.HXType, "HeatExchanger:Desiccant:BalancedFlow")) {
694 0 : ShowWarningError(state, format("{} = \"{}\"", desicDehum.DehumType, desicDehum.Name));
695 0 : ShowContinueError(state, format("Invalid {} = {}", cAlphaFields(3), desicDehum.HXType));
696 0 : ErrorsFoundGeneric = true;
697 : } else {
698 4 : desicDehum.HXTypeNum = BalancedHX;
699 : }
700 :
701 4 : ErrorsFound2 = false;
702 4 : ValidateComponent(state, desicDehum.HXType, desicDehum.HXName, ErrorsFound2, desicDehum.DehumType + " = \"" + desicDehum.Name + "\"");
703 4 : if (ErrorsFound2) {
704 0 : ErrorsFoundGeneric = true;
705 : }
706 :
707 4 : ErrorsFound2 = false;
708 4 : desicDehum.HXProcInNode = HeatRecovery::GetSecondaryInletNode(state, desicDehum.HXName, ErrorsFound2);
709 4 : if (ErrorsFound2) {
710 0 : ShowContinueError(state, format("...occurs in {} \"{}\"", desicDehum.DehumType, desicDehum.Name));
711 0 : ErrorsFoundGeneric = true;
712 : }
713 :
714 4 : std::string ProcAirInlet = state.dataLoopNodes->NodeID(desicDehum.HXProcInNode);
715 :
716 4 : desicDehum.ProcAirInNode = NodeInputManager::GetOnlySingleNode(state,
717 : ProcAirInlet,
718 : ErrorsFound,
719 : DataLoopNode::ConnectionObjectType::DehumidifierDesiccantSystem,
720 4 : desicDehum.Name,
721 : DataLoopNode::NodeFluidType::Air,
722 : DataLoopNode::ConnectionType::Inlet,
723 : NodeInputManager::CompFluidStream::Primary,
724 : DataLoopNode::ObjectIsParent);
725 :
726 4 : ErrorsFound2 = false;
727 4 : desicDehum.HXProcOutNode = HeatRecovery::GetSecondaryOutletNode(state, desicDehum.HXName, ErrorsFound2);
728 4 : if (ErrorsFound2) {
729 0 : ShowContinueError(state, format("...occurs in {} \"{}\"", desicDehum.DehumType, desicDehum.Name));
730 0 : ErrorsFoundGeneric = true;
731 : }
732 :
733 4 : std::string ProcAirOutlet = state.dataLoopNodes->NodeID(desicDehum.HXProcOutNode);
734 :
735 8 : desicDehum.ProcAirOutNode = NodeInputManager::GetOnlySingleNode(state,
736 : ProcAirOutlet,
737 : ErrorsFound,
738 : DataLoopNode::ConnectionObjectType::DehumidifierDesiccantSystem,
739 4 : desicDehum.Name,
740 : DataLoopNode::NodeFluidType::Air,
741 : DataLoopNode::ConnectionType::Outlet,
742 : NodeInputManager::CompFluidStream::Primary,
743 : DataLoopNode::ObjectIsParent);
744 :
745 4 : BranchNodeConnections::TestCompSet(state, desicDehum.DehumType, desicDehum.Name, ProcAirInlet, ProcAirOutlet, "Process Air Nodes");
746 :
747 4 : ErrorsFound2 = false;
748 4 : desicDehum.HXRegenInNode = HeatRecovery::GetSupplyInletNode(state, desicDehum.HXName, ErrorsFound2);
749 4 : if (ErrorsFound2) {
750 0 : ShowContinueError(state, format("...occurs in {} \"{}\"", desicDehum.DehumType, desicDehum.Name));
751 0 : ErrorsFoundGeneric = true;
752 : }
753 :
754 4 : ErrorsFound2 = false;
755 4 : desicDehum.HXRegenOutNode = HeatRecovery::GetSupplyOutletNode(state, desicDehum.HXName, ErrorsFound2);
756 4 : if (ErrorsFound2) {
757 0 : ShowContinueError(state, format("...occurs in {} \"{}\"", desicDehum.DehumType, desicDehum.Name));
758 0 : ErrorsFoundGeneric = true;
759 : }
760 :
761 4 : desicDehum.ControlNodeNum = NodeInputManager::GetOnlySingleNode(state,
762 4 : Alphas(5),
763 : ErrorsFound,
764 : DataLoopNode::ConnectionObjectType::DehumidifierDesiccantSystem,
765 4 : desicDehum.Name,
766 : DataLoopNode::NodeFluidType::Air,
767 : DataLoopNode::ConnectionType::Sensor,
768 : NodeInputManager::CompFluidStream::Primary,
769 : DataLoopNode::ObjectIsNotParent);
770 :
771 4 : if (desicDehum.ControlNodeNum == 0) {
772 0 : ShowSevereError(state, format("{} = \"{}\"", desicDehum.DehumType, desicDehum.Name));
773 0 : ShowContinueError(state, format("{} must be specified.", cAlphaFields(5)));
774 0 : ErrorsFoundGeneric = true;
775 : }
776 :
777 4 : desicDehum.regenFanType = static_cast<HVAC::FanType>(getEnumValue(HVAC::fanTypeNamesUC, Alphas(6)));
778 4 : assert(desicDehum.regenFanType != HVAC::FanType::Invalid);
779 :
780 4 : desicDehum.RegenFanName = Alphas(7);
781 :
782 4 : if (desicDehum.regenFanType == HVAC::FanType::OnOff || desicDehum.regenFanType == HVAC::FanType::Constant ||
783 2 : desicDehum.regenFanType == HVAC::FanType::SystemModel) {
784 4 : ErrorsFound2 = false;
785 8 : ValidateComponent(state,
786 4 : HVAC::fanTypeNamesUC[(int)desicDehum.regenFanType],
787 4 : desicDehum.RegenFanName,
788 : ErrorsFound2,
789 8 : desicDehum.DehumType + " \"" + desicDehum.Name + "\"");
790 4 : if (ErrorsFound2) {
791 0 : ErrorsFoundGeneric = true;
792 : }
793 : } else {
794 0 : ShowSevereError(state, format("{} \"{}\"", desicDehum.DehumType, desicDehum.Name));
795 0 : ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(6), HVAC::fanTypeNamesUC[(int)desicDehum.regenFanType]));
796 0 : ErrorsFoundGeneric = true;
797 : }
798 :
799 4 : desicDehum.regenFanPlace = static_cast<HVAC::FanPlace>(getEnumValue(HVAC::fanPlaceNamesUC, Alphas(8)));
800 4 : if (desicDehum.regenFanPlace == HVAC::FanPlace::Invalid) {
801 0 : ShowWarningInvalidKey(state, eoh, cAlphaFields(8), Alphas(8), "DrawThrough");
802 0 : desicDehum.regenFanPlace = HVAC::FanPlace::DrawThru;
803 : }
804 :
805 4 : ErrorsFound2 = false;
806 4 : desicDehum.RegenFanIndex = Fans::GetFanIndex(state, desicDehum.RegenFanName);
807 4 : if (desicDehum.RegenFanIndex == 0) {
808 0 : ShowSevereItemNotFound(state, eoh, cAlphaFields(7), desicDehum.RegenFanName);
809 0 : ErrorsFoundGeneric = true;
810 : } else {
811 4 : auto *fan = state.dataFans->fans(desicDehum.RegenFanIndex);
812 4 : assert(desicDehum.regenFanType == fan->type);
813 4 : desicDehum.RegenFanInNode = fan->inletNodeNum;
814 4 : desicDehum.RegenFanOutNode = fan->outletNodeNum;
815 : }
816 :
817 4 : desicDehum.RegenCoilType = Alphas(9);
818 4 : desicDehum.RegenCoilName = Alphas(10);
819 4 : RegenCoilType = Alphas(9);
820 4 : RegenCoilName = Alphas(10);
821 4 : desicDehum.RegenSetPointTemp = Numbers(1);
822 :
823 4 : if (!lAlphaBlanks(10)) {
824 8 : if (Util::SameString(desicDehum.RegenCoilType, "Coil:Heating:Electric") ||
825 8 : Util::SameString(desicDehum.RegenCoilType, "Coil:Heating:Fuel")) {
826 4 : if (Util::SameString(desicDehum.RegenCoilType, "Coil:Heating:Electric")) {
827 0 : desicDehum.RegenCoilType_Num = HVAC::Coil_HeatingElectric;
828 : }
829 4 : if (Util::SameString(desicDehum.RegenCoilType, "Coil:Heating:Fuel")) {
830 4 : desicDehum.RegenCoilType_Num = HVAC::Coil_HeatingGasOrOtherFuel;
831 : }
832 4 : ErrorsFound2 = false;
833 4 : ValidateComponent(state, RegenCoilType, RegenCoilName, ErrorsFound2, desicDehum.DehumType + " \"" + desicDehum.Name + "\"");
834 4 : if (ErrorsFound2) {
835 0 : ErrorsFoundGeneric = true;
836 : }
837 :
838 4 : if (desicDehum.RegenSetPointTemp <= 0.0) {
839 0 : ShowSevereError(state, format("{} \"{}\"", desicDehum.DehumType, desicDehum.Name));
840 0 : ShowContinueError(state, format("{} must be greater than 0.", cNumericFields(1)));
841 0 : ErrorsFoundGeneric = true;
842 : }
843 :
844 4 : ErrorsFound2 = false;
845 4 : desicDehum.RegenCoilInletNode = HeatingCoils::GetCoilInletNode(state, RegenCoilType, RegenCoilName, ErrorsFound2);
846 4 : if (ErrorsFound2) {
847 0 : ShowContinueError(state, format("...occurs in {} \"{}\"", desicDehum.DehumType, desicDehum.Name));
848 0 : ErrorsFoundGeneric = true;
849 : }
850 :
851 4 : ErrorsFound2 = false;
852 4 : desicDehum.RegenCoilOutletNode = HeatingCoils::GetCoilOutletNode(state, RegenCoilType, RegenCoilName, ErrorsFound2);
853 4 : if (ErrorsFound2) {
854 0 : ShowContinueError(state, format("...occurs in {} \"{}\"", desicDehum.DehumType, desicDehum.Name));
855 0 : ErrorsFoundGeneric = true;
856 : }
857 :
858 4 : ErrorsFound2 = false;
859 4 : HeatingCoils::GetCoilIndex(state, RegenCoilName, desicDehum.RegenCoilIndex, ErrorsFound2);
860 4 : if (ErrorsFound2) {
861 0 : ShowContinueError(state, format("...occurs in {} \"{}\"", desicDehum.DehumType, desicDehum.Name));
862 0 : ErrorsFoundGeneric = true;
863 : }
864 :
865 4 : ErrorsFound2 = false;
866 4 : RegenCoilControlNodeNum = HeatingCoils::GetCoilControlNodeNum(state, RegenCoilType, RegenCoilName, ErrorsFound2);
867 4 : if (ErrorsFound2) {
868 0 : ShowContinueError(state, format("...occurs in {} \"{}\"", desicDehum.DehumType, desicDehum.Name));
869 0 : ErrorsFoundGeneric = true;
870 : }
871 :
872 4 : if (RegenCoilControlNodeNum > 0) {
873 0 : ShowSevereError(state, format("{} \"{}\"", desicDehum.DehumType, desicDehum.Name));
874 0 : ShowContinueError(state,
875 0 : format("{} is specified as {:.3R} C in this object.", cNumericFields(1), desicDehum.RegenSetPointTemp));
876 0 : ShowContinueError(state, " Do not specify a coil temperature setpoint node name in the regeneration air heater object.");
877 0 : ShowContinueError(state, format("...{} = {}", cAlphaFields(9), desicDehum.RegenCoilType));
878 0 : ShowContinueError(state, format("...{} = {}", cAlphaFields(10), desicDehum.RegenCoilName));
879 0 : ShowContinueError(
880 0 : state, format("...heating coil temperature setpoint node = {}", state.dataLoopNodes->NodeID(RegenCoilControlNodeNum)));
881 0 : ShowContinueError(state, "...leave the heating coil temperature setpoint node name blank in the regen heater object.");
882 0 : ErrorsFoundGeneric = true;
883 : }
884 :
885 4 : RegairHeatingCoilFlag = true;
886 4 : HeatingCoils::SetHeatingCoilData(state, desicDehum.RegenCoilIndex, ErrorsFound2, RegairHeatingCoilFlag, DesicDehumNum);
887 4 : if (ErrorsFound2) {
888 0 : ShowContinueError(state, format("...occurs in {} \"{}\"", desicDehum.DehumType, desicDehum.Name));
889 0 : ErrorsFoundGeneric = true;
890 : }
891 :
892 0 : } else if (Util::SameString(desicDehum.RegenCoilType, "Coil:Heating:Water")) {
893 0 : desicDehum.RegenCoilType_Num = HVAC::Coil_HeatingWater;
894 0 : ValidateComponent(state, RegenCoilType, RegenCoilName, IsNotOK, CurrentModuleObject);
895 0 : if (IsNotOK) {
896 0 : ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
897 0 : ErrorsFound = true;
898 : } else { // mine data from heating coil object
899 0 : errFlag = false;
900 0 : desicDehum.RegenCoilIndex = WaterCoils::GetWaterCoilIndex(state, "COIL:HEATING:WATER", RegenCoilName, errFlag);
901 0 : if (desicDehum.RegenCoilIndex == 0) {
902 0 : ShowSevereError(state, format("{} illegal {} = {}", CurrentModuleObject, cAlphaFields(9), RegenCoilName));
903 0 : ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, desicDehum.Name));
904 0 : ErrorsFound = true;
905 : }
906 :
907 0 : if (desicDehum.RegenSetPointTemp <= 0.0) {
908 0 : ShowSevereError(state, format("{} \"{}\"", desicDehum.DehumType, desicDehum.Name));
909 0 : ShowContinueError(state, format("{} must be greater than 0.", cNumericFields(1)));
910 0 : ErrorsFoundGeneric = true;
911 : }
912 :
913 : // Get the Heating Coil Hot water Inlet or control Node number
914 0 : errFlag = false;
915 0 : desicDehum.CoilControlNode = WaterCoils::GetCoilWaterInletNode(state, "Coil:Heating:Water", RegenCoilName, errFlag);
916 0 : if (errFlag) {
917 0 : ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, desicDehum.Name));
918 0 : ErrorsFound = true;
919 : }
920 :
921 : // Get the Regeneration Heating Coil hot water max volume flow rate
922 0 : errFlag = false;
923 0 : desicDehum.MaxCoilFluidFlow = WaterCoils::GetCoilMaxWaterFlowRate(state, "Coil:Heating:Water", RegenCoilName, errFlag);
924 0 : if (errFlag) {
925 0 : ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, desicDehum.Name));
926 0 : ErrorsFound = true;
927 : }
928 :
929 : // Get the Regeneration Heating Coil Inlet Node
930 0 : errFlag = false;
931 0 : int RegenCoilAirInletNode = WaterCoils::GetCoilInletNode(state, "Coil:Heating:Water", RegenCoilName, errFlag);
932 0 : desicDehum.RegenCoilInletNode = RegenCoilAirInletNode;
933 0 : if (errFlag) {
934 0 : ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, desicDehum.Name));
935 0 : ErrorsFound = true;
936 : }
937 :
938 : // Get the Regeneration Heating Coil Outlet Node
939 0 : errFlag = false;
940 0 : int RegenCoilAirOutletNode = WaterCoils::GetCoilOutletNode(state, "Coil:Heating:Water", RegenCoilName, errFlag);
941 0 : desicDehum.RegenCoilOutletNode = RegenCoilAirOutletNode;
942 0 : if (errFlag) {
943 0 : ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, desicDehum.Name));
944 0 : ErrorsFound = true;
945 : }
946 :
947 0 : RegairHeatingCoilFlag = true;
948 0 : WaterCoils::SetWaterCoilData(state, desicDehum.RegenCoilIndex, ErrorsFound2, RegairHeatingCoilFlag, DesicDehumNum);
949 0 : if (ErrorsFound2) {
950 0 : ShowContinueError(state, format("...occurs in {} \"{}\"", desicDehum.DehumType, desicDehum.Name));
951 0 : ErrorsFoundGeneric = true;
952 : }
953 : }
954 0 : } else if (Util::SameString(desicDehum.RegenCoilType, "Coil:Heating:Steam")) {
955 0 : desicDehum.RegenCoilType_Num = HVAC::Coil_HeatingSteam;
956 0 : ValidateComponent(state, RegenCoilType, RegenCoilName, IsNotOK, CurrentModuleObject);
957 0 : if (IsNotOK) {
958 0 : ShowContinueError(state, format("...occurs in {} = {}", CurrentModuleObject, Alphas(1)));
959 0 : ErrorsFound = true;
960 : } else { // mine data from the regeneration heating coil object
961 0 : if (desicDehum.RegenSetPointTemp <= 0.0) {
962 0 : ShowSevereError(state, format("{} \"{}\"", desicDehum.DehumType, desicDehum.Name));
963 0 : ShowContinueError(state, format("{} must be greater than 0.", cNumericFields(1)));
964 0 : ErrorsFoundGeneric = true;
965 : }
966 :
967 0 : errFlag = false;
968 0 : desicDehum.RegenCoilIndex = SteamCoils::GetSteamCoilIndex(state, "COIL:HEATING:STEAM", RegenCoilName, errFlag);
969 0 : if (desicDehum.RegenCoilIndex == 0) {
970 0 : ShowSevereError(state, format("{} illegal {} = {}", CurrentModuleObject, cAlphaFields(9), RegenCoilName));
971 0 : ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, desicDehum.Name));
972 0 : ErrorsFound = true;
973 : }
974 :
975 : // Get the regeneration Heating Coil steam inlet node number
976 0 : errFlag = false;
977 0 : desicDehum.CoilControlNode = SteamCoils::GetCoilSteamInletNode(state, "Coil:Heating:Steam", RegenCoilName, errFlag);
978 0 : if (errFlag) {
979 0 : ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, desicDehum.Name));
980 0 : ErrorsFound = true;
981 : }
982 :
983 : // Get the regeneration heating Coil steam max volume flow rate
984 0 : desicDehum.MaxCoilFluidFlow = SteamCoils::GetCoilMaxSteamFlowRate(state, desicDehum.RegenCoilIndex, errFlag);
985 0 : if (desicDehum.MaxCoilFluidFlow > 0.0) {
986 0 : Real64 SteamDensity = Fluid::GetSteam(state)->getSatDensity(state, TempSteamIn, 1.0, dehumidifierDesiccantNoFans);
987 0 : desicDehum.MaxCoilFluidFlow *= SteamDensity;
988 : }
989 :
990 : // Get the regeneration heating Coil Inlet Node
991 0 : errFlag = false;
992 0 : int RegenCoilAirInletNode = SteamCoils::GetCoilAirInletNode(state, desicDehum.RegenCoilIndex, RegenCoilName, errFlag);
993 0 : desicDehum.RegenCoilInletNode = RegenCoilAirInletNode;
994 0 : if (errFlag) {
995 0 : ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, desicDehum.Name));
996 0 : ErrorsFound = true;
997 : }
998 :
999 : // Get the regeneration heating Coil Outlet Node
1000 0 : errFlag = false;
1001 0 : int RegenCoilAirOutletNode = SteamCoils::GetCoilAirOutletNode(state, desicDehum.RegenCoilIndex, RegenCoilName, errFlag);
1002 0 : desicDehum.RegenCoilOutletNode = RegenCoilAirOutletNode;
1003 0 : if (errFlag) {
1004 0 : ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, desicDehum.Name));
1005 0 : ErrorsFound = true;
1006 : }
1007 : }
1008 :
1009 0 : ErrorsFound2 = false;
1010 0 : RegenCoilControlNodeNum = SteamCoils::GetSteamCoilControlNodeNum(state, RegenCoilType, RegenCoilName, ErrorsFound2);
1011 :
1012 0 : if (ErrorsFound2) {
1013 0 : ShowContinueError(state, format("...occurs in {} \"{}\"", desicDehum.DehumType, desicDehum.Name));
1014 0 : ErrorsFoundGeneric = true;
1015 : }
1016 :
1017 0 : if (RegenCoilControlNodeNum > 0) {
1018 0 : ShowSevereError(state, format("{} \"{}\"", desicDehum.DehumType, desicDehum.Name));
1019 0 : ShowContinueError(state,
1020 0 : format("{} is specified as {:.3R} C in this object.", cNumericFields(1), desicDehum.RegenSetPointTemp));
1021 0 : ShowContinueError(state, " Do not specify a coil temperature setpoint node name in the regeneration air heater object.");
1022 0 : ShowContinueError(state, format("...{} = {}", cAlphaFields(9), desicDehum.RegenCoilType));
1023 0 : ShowContinueError(state, format("...{} = {}", cAlphaFields(10), desicDehum.RegenCoilName));
1024 0 : ShowContinueError(
1025 0 : state, format("...heating coil temperature setpoint node = {}", state.dataLoopNodes->NodeID(RegenCoilControlNodeNum)));
1026 0 : ShowContinueError(state, "...leave the heating coil temperature setpoint node name blank in the regen heater object.");
1027 0 : ErrorsFoundGeneric = true;
1028 : }
1029 :
1030 0 : RegairHeatingCoilFlag = true;
1031 0 : SteamCoils::SetSteamCoilData(state, desicDehum.RegenCoilIndex, ErrorsFound2, RegairHeatingCoilFlag, DesicDehumNum);
1032 0 : if (ErrorsFound2) {
1033 0 : ShowContinueError(state, format("...occurs in {} \"{}\"", desicDehum.DehumType, desicDehum.Name));
1034 0 : ErrorsFoundGeneric = true;
1035 : }
1036 :
1037 : } else {
1038 0 : ShowSevereError(state, format("{} \"{}\"", desicDehum.DehumType, desicDehum.Name));
1039 0 : ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(9), desicDehum.RegenCoilType));
1040 0 : ErrorsFoundGeneric = true;
1041 : }
1042 : }
1043 :
1044 4 : std::string RegenAirInlet = state.dataLoopNodes->NodeID(desicDehum.HXRegenInNode);
1045 :
1046 4 : std::string RegenAirOutlet = state.dataLoopNodes->NodeID(desicDehum.HXRegenOutNode);
1047 :
1048 4 : std::string RegenFanInlet = state.dataLoopNodes->NodeID(desicDehum.RegenFanInNode);
1049 :
1050 4 : std::string RegenFanOutlet = state.dataLoopNodes->NodeID(desicDehum.RegenFanOutNode);
1051 :
1052 4 : if (!lAlphaBlanks(10)) {
1053 4 : RegenCoilInlet = state.dataLoopNodes->NodeID(desicDehum.RegenCoilInletNode);
1054 :
1055 4 : RegenCoilOutlet = state.dataLoopNodes->NodeID(desicDehum.RegenCoilOutletNode);
1056 : }
1057 :
1058 4 : BranchNodeConnections::SetUpCompSets(
1059 : state, desicDehum.DehumType, desicDehum.Name, desicDehum.HXType, desicDehum.HXName, ProcAirInlet, ProcAirOutlet);
1060 :
1061 8 : BranchNodeConnections::SetUpCompSets(state,
1062 : desicDehum.DehumType,
1063 : desicDehum.Name,
1064 4 : HVAC::fanTypeNamesUC[(int)desicDehum.regenFanType],
1065 : desicDehum.RegenFanName,
1066 : RegenFanInlet,
1067 : RegenFanOutlet);
1068 :
1069 4 : if (!lAlphaBlanks(10)) {
1070 4 : BranchNodeConnections::SetUpCompSets(state,
1071 : desicDehum.DehumType,
1072 : desicDehum.Name,
1073 : desicDehum.RegenCoilType,
1074 : desicDehum.RegenCoilName,
1075 : RegenCoilInlet,
1076 : RegenCoilOutlet);
1077 : }
1078 :
1079 4 : if (desicDehum.regenFanPlace == HVAC::FanPlace::BlowThru) {
1080 0 : desicDehum.RegenAirInNode = NodeInputManager::GetOnlySingleNode(state,
1081 : RegenFanInlet,
1082 : ErrorsFound,
1083 : DataLoopNode::ConnectionObjectType::DehumidifierDesiccantSystem,
1084 0 : desicDehum.Name,
1085 : DataLoopNode::NodeFluidType::Air,
1086 : DataLoopNode::ConnectionType::Inlet,
1087 : NodeInputManager::CompFluidStream::Primary,
1088 : DataLoopNode::ObjectIsParent);
1089 0 : desicDehum.RegenAirOutNode = NodeInputManager::GetOnlySingleNode(state,
1090 : RegenAirOutlet,
1091 : ErrorsFound,
1092 : DataLoopNode::ConnectionObjectType::DehumidifierDesiccantSystem,
1093 0 : desicDehum.Name,
1094 : DataLoopNode::NodeFluidType::Air,
1095 : DataLoopNode::ConnectionType::Outlet,
1096 : NodeInputManager::CompFluidStream::Primary,
1097 : DataLoopNode::ObjectIsParent);
1098 0 : if (!lAlphaBlanks(10)) {
1099 0 : if (desicDehum.RegenFanOutNode != desicDehum.RegenCoilInletNode) {
1100 0 : ShowSevereError(state, format("{} \"{}\"", desicDehum.DehumType, desicDehum.Name));
1101 0 : ShowContinueError(state,
1102 : "Regen fan outlet node name and regen heater inlet node name do not match for fan placement: Blow Through");
1103 0 : ShowContinueError(state, format("...Regen fan outlet node = {}", state.dataLoopNodes->NodeID(desicDehum.RegenFanOutNode)));
1104 0 : ShowContinueError(state,
1105 0 : format("...Regen heater inlet node = {}", state.dataLoopNodes->NodeID(desicDehum.RegenCoilInletNode)));
1106 0 : ErrorsFoundGeneric = true;
1107 : }
1108 0 : if (desicDehum.RegenCoilOutletNode != desicDehum.HXRegenInNode) {
1109 0 : ShowSevereError(state, format("{} \"{}\"", desicDehum.DehumType, desicDehum.Name));
1110 0 : ShowContinueError(state,
1111 : "Regen heater outlet node name and desiccant heat exchanger regen inlet node name do not match for fan "
1112 : "placement: Blow Through");
1113 0 : ShowContinueError(state,
1114 0 : format("...Regen heater outlet node = {}", state.dataLoopNodes->NodeID(desicDehum.RegenCoilOutletNode)));
1115 0 : ShowContinueError(state, format("...HX regen inlet node = {}", state.dataLoopNodes->NodeID(desicDehum.HXRegenInNode)));
1116 0 : ErrorsFoundGeneric = true;
1117 : }
1118 : } else {
1119 0 : if (desicDehum.RegenFanOutNode != desicDehum.HXRegenInNode) {
1120 0 : ShowSevereError(state, format("{} \"{}\"", desicDehum.DehumType, desicDehum.Name));
1121 0 : ShowContinueError(
1122 : state,
1123 : "Regen fan outlet node name and desiccant heat exchanger inlet node name do not match for fan placement: Blow Through");
1124 0 : ShowContinueError(state, format("...Regen fan outlet node = {}", state.dataLoopNodes->NodeID(desicDehum.RegenFanOutNode)));
1125 0 : ShowContinueError(state, format("...Desiccant HX inlet node = {}", state.dataLoopNodes->NodeID(desicDehum.HXRegenInNode)));
1126 0 : ErrorsFoundGeneric = true;
1127 : }
1128 : }
1129 : } else { // ELSE for IF (desicDehum%RegenFanPlacement == HVAC::BlowThru)THEN
1130 4 : desicDehum.RegenAirOutNode = NodeInputManager::GetOnlySingleNode(state,
1131 : RegenFanOutlet,
1132 : ErrorsFound,
1133 : DataLoopNode::ConnectionObjectType::DehumidifierDesiccantSystem,
1134 4 : desicDehum.Name,
1135 : DataLoopNode::NodeFluidType::Air,
1136 : DataLoopNode::ConnectionType::Outlet,
1137 : NodeInputManager::CompFluidStream::Primary,
1138 : DataLoopNode::ObjectIsParent);
1139 4 : if (!lAlphaBlanks(10)) {
1140 4 : desicDehum.RegenAirInNode = NodeInputManager::GetOnlySingleNode(state,
1141 : RegenCoilInlet,
1142 : ErrorsFound,
1143 : DataLoopNode::ConnectionObjectType::DehumidifierDesiccantSystem,
1144 4 : desicDehum.Name,
1145 : DataLoopNode::NodeFluidType::Air,
1146 : DataLoopNode::ConnectionType::Inlet,
1147 : NodeInputManager::CompFluidStream::Primary,
1148 : DataLoopNode::ObjectIsParent);
1149 4 : if (desicDehum.RegenCoilOutletNode != desicDehum.HXRegenInNode) {
1150 0 : ShowSevereError(state, format("{} \"{}\"", desicDehum.DehumType, desicDehum.Name));
1151 0 : ShowContinueError(state,
1152 : "Regen heater outlet node name and desiccant heat exchanger regen inlet node name do not match for fan "
1153 : "placement: Draw Through");
1154 0 : ShowContinueError(state,
1155 0 : format("...Regen heater outlet node = {}", state.dataLoopNodes->NodeID(desicDehum.RegenCoilOutletNode)));
1156 0 : ShowContinueError(state, format("...HX regen inlet node = {}", state.dataLoopNodes->NodeID(desicDehum.HXRegenInNode)));
1157 0 : ErrorsFoundGeneric = true;
1158 : }
1159 : } else {
1160 0 : desicDehum.RegenAirInNode = NodeInputManager::GetOnlySingleNode(state,
1161 : RegenAirInlet,
1162 : ErrorsFound,
1163 : DataLoopNode::ConnectionObjectType::DehumidifierDesiccantSystem,
1164 0 : desicDehum.Name,
1165 : DataLoopNode::NodeFluidType::Air,
1166 : DataLoopNode::ConnectionType::Inlet,
1167 : NodeInputManager::CompFluidStream::Primary,
1168 : DataLoopNode::ObjectIsParent);
1169 : }
1170 4 : if (desicDehum.RegenFanInNode != desicDehum.HXRegenOutNode) {
1171 0 : ShowSevereError(state, format("{} \"{}\"", desicDehum.DehumType, desicDehum.Name));
1172 0 : ShowContinueError(
1173 : state,
1174 : "Regen fan inlet node name and desiccant heat exchanger regen outlet node name do not match for fan placement: Draw Through");
1175 0 : ShowContinueError(state, format("...Regen fan inlet node = {}", state.dataLoopNodes->NodeID(desicDehum.RegenFanInNode)));
1176 0 : ShowContinueError(state, format("...HX regen outlet node = {}", state.dataLoopNodes->NodeID(desicDehum.HXRegenOutNode)));
1177 0 : ErrorsFoundGeneric = true;
1178 : }
1179 : }
1180 :
1181 4 : desicDehum.CoolingCoilType = Alphas(11);
1182 4 : desicDehum.CoolingCoilName = Alphas(12);
1183 :
1184 4 : if (!lAlphaBlanks(12)) {
1185 3 : if ((Util::SameString(desicDehum.CoolingCoilType, "COIL:COOLING:DX:SINGLESPEED")) ||
1186 3 : (Util::SameString(desicDehum.CoolingCoilType, "COIL:COOLING:DX:TWOSTAGEWITHHUMIDITYCONTROLMODE")) ||
1187 3 : (Util::SameString(desicDehum.CoolingCoilType, "COIL:COOLING:DX:VARIABLESPEED"))) {
1188 2 : ErrorsFound2 = false;
1189 4 : ValidateComponent(state,
1190 : desicDehum.CoolingCoilType,
1191 2 : desicDehum.CoolingCoilName,
1192 : ErrorsFound2,
1193 4 : desicDehum.DehumType + " \"" + desicDehum.Name + "\"");
1194 2 : if (ErrorsFound2) {
1195 0 : ErrorsFoundGeneric = true;
1196 : }
1197 :
1198 2 : if ((Util::SameString(desicDehum.CoolingCoilType, "COIL:COOLING:DX:SINGLESPEED"))) {
1199 1 : desicDehum.coolingCoil_TypeNum = HVAC::CoilDX_CoolingSingleSpeed;
1200 1 : } else if ((Util::SameString(desicDehum.CoolingCoilType, "COIL:COOLING:DX:TWOSTAGEWITHHUMIDITYCONTROLMODE"))) {
1201 0 : desicDehum.coolingCoil_TypeNum = HVAC::CoilDX_CoolingTwoStageWHumControl;
1202 1 : } else if ((Util::SameString(desicDehum.CoolingCoilType, "COIL:COOLING:DX:VARIABLESPEED"))) {
1203 1 : desicDehum.coolingCoil_TypeNum = HVAC::Coil_CoolingAirToAirVariableSpeed;
1204 : }
1205 :
1206 : } else {
1207 0 : ShowSevereError(state, format("{}={}", desicDehum.DehumType, desicDehum.Name));
1208 0 : ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(11), desicDehum.CoolingCoilType));
1209 0 : ErrorsFoundGeneric = true;
1210 : }
1211 :
1212 2 : if ((desicDehum.coolingCoil_TypeNum == HVAC::CoilDX_CoolingSingleSpeed) ||
1213 1 : (desicDehum.coolingCoil_TypeNum == HVAC::CoilDX_CoolingTwoStageWHumControl)) {
1214 1 : ErrorsFound2 = false;
1215 1 : desicDehum.CoolingCoilOutletNode =
1216 1 : DXCoils::GetCoilOutletNode(state, desicDehum.CoolingCoilType, desicDehum.CoolingCoilName, ErrorsFound2);
1217 1 : desicDehum.CompanionCoilCapacity =
1218 1 : DXCoils::GetCoilCapacity(state, desicDehum.CoolingCoilType, desicDehum.CoolingCoilName, ErrorsFound2);
1219 1 : if (ErrorsFound2) {
1220 0 : ShowContinueError(state, format("...occurs in {} \"{}\"", desicDehum.DehumType, desicDehum.CoolingCoilName));
1221 : }
1222 :
1223 1 : ErrorsFound2 = false;
1224 1 : DXCoils::GetDXCoilIndex(state, desicDehum.CoolingCoilName, desicDehum.DXCoilIndex, ErrorsFound2, desicDehum.CoolingCoilType);
1225 1 : if (ErrorsFound2) {
1226 0 : ShowContinueError(state, format("...occurs in {} \"{}\"", desicDehum.DehumType, desicDehum.CoolingCoilName));
1227 : }
1228 1 : } else if (desicDehum.coolingCoil_TypeNum == HVAC::Coil_CoolingAirToAirVariableSpeed) {
1229 1 : ErrorsFound2 = false;
1230 2 : desicDehum.CoolingCoilOutletNode = VariableSpeedCoils::GetCoilOutletNodeVariableSpeed(
1231 1 : state, desicDehum.CoolingCoilType, desicDehum.CoolingCoilName, ErrorsFound2);
1232 1 : ErrorsFound2 = false;
1233 1 : desicDehum.CompanionCoilCapacity =
1234 1 : VariableSpeedCoils::GetCoilCapacityVariableSpeed(state, desicDehum.CoolingCoilType, desicDehum.CoolingCoilName, ErrorsFound2);
1235 1 : if (ErrorsFound2) {
1236 0 : ShowContinueError(state, format("...occurs in {} \"{}\"", desicDehum.DehumType, desicDehum.CoolingCoilName));
1237 : }
1238 1 : ErrorsFound2 = false;
1239 1 : desicDehum.DXCoilIndex =
1240 1 : VariableSpeedCoils::GetCoilIndexVariableSpeed(state, desicDehum.CoolingCoilType, desicDehum.CoolingCoilName, ErrorsFound2);
1241 1 : if (ErrorsFound2) {
1242 0 : ShowContinueError(state, format("...occurs in {} \"{}\"", desicDehum.DehumType, desicDehum.CoolingCoilName));
1243 : }
1244 : }
1245 :
1246 : } // (desicDehum%CoolingCoilName /= Blank)THEN
1247 :
1248 4 : if (Util::SameString(Alphas(13), "Yes")) {
1249 2 : desicDehum.CoilUpstreamOfProcessSide = Selection::Yes;
1250 2 : } else if (lAlphaBlanks(13)) {
1251 2 : desicDehum.CoilUpstreamOfProcessSide = Selection::No;
1252 0 : } else if (Util::SameString(Alphas(13), "No")) {
1253 0 : desicDehum.CoilUpstreamOfProcessSide = Selection::No;
1254 : } else {
1255 0 : ShowWarningError(state, format("{} \"{}\"", desicDehum.DehumType, desicDehum.Name));
1256 0 : ShowContinueError(state, format("Invalid choice for {} = {}", cAlphaFields(13), Alphas(13)));
1257 0 : ShowContinueError(state, "...resetting to the default value of No");
1258 0 : desicDehum.CoilUpstreamOfProcessSide = Selection::No;
1259 : }
1260 :
1261 4 : if (Util::SameString(Alphas(14), "Yes")) {
1262 2 : desicDehum.Preheat = Selection::Yes;
1263 2 : } else if (Util::SameString(Alphas(14), "No")) {
1264 2 : desicDehum.Preheat = Selection::No;
1265 0 : } else if (lAlphaBlanks(14)) {
1266 0 : desicDehum.Preheat = Selection::No;
1267 : } else {
1268 0 : ShowWarningError(state, format("{} \"{}\"", desicDehum.DehumType, desicDehum.Name));
1269 0 : ShowContinueError(state, format("Invalid choice for {} = {}", cAlphaFields(14), Alphas(14)));
1270 0 : ShowContinueError(state, "...resetting to the default value of NO");
1271 0 : desicDehum.Preheat = Selection::No;
1272 : }
1273 :
1274 4 : if (desicDehum.DXCoilIndex > 0) {
1275 :
1276 2 : if (desicDehum.Preheat == Selection::Yes) { // Companion coil waste heat used for regeneration of desiccant
1277 2 : ErrorsFound2 = false;
1278 : DesuperHeaterIndex =
1279 2 : HeatingCoils::GetHeatReclaimSourceIndex(state, desicDehum.CoolingCoilType, desicDehum.CoolingCoilName, ErrorsFound2);
1280 2 : if (ErrorsFound2) {
1281 0 : ShowContinueError(state, format("...occurs in {} \"{}\"", desicDehum.DehumType, desicDehum.Name));
1282 0 : ErrorsFoundGeneric = true;
1283 : }
1284 :
1285 2 : if (DesuperHeaterIndex > 0) {
1286 0 : ShowWarningError(state, format("{}={}", desicDehum.DehumType, desicDehum.Name));
1287 0 : ShowContinueError(state,
1288 : "A Coil:Heating:Desuperheater object should not be used when condenser waste heat is reclaimed for "
1289 : "desiccant regeneration.");
1290 0 : ShowContinueError(state,
1291 0 : format("A Coil:Heating:Desuperheater object was found using waste heat from the {} \"{}\" object.",
1292 0 : desicDehum.CoolingCoilType,
1293 0 : desicDehum.CoolingCoilName));
1294 : // ErrorsFoundGeneric = .TRUE.
1295 : }
1296 : }
1297 2 : if ((desicDehum.coolingCoil_TypeNum == HVAC::CoilDX_CoolingSingleSpeed) ||
1298 1 : (desicDehum.coolingCoil_TypeNum == HVAC::CoilDX_CoolingTwoStageWHumControl)) {
1299 1 : ErrorsFound2 = false;
1300 1 : desicDehum.CondenserInletNode =
1301 1 : DXCoils::GetCoilCondenserInletNode(state, desicDehum.CoolingCoilType, desicDehum.CoolingCoilName, ErrorsFound2);
1302 1 : } else if (desicDehum.coolingCoil_TypeNum == HVAC::Coil_CoolingAirToAirVariableSpeed) {
1303 1 : ErrorsFound2 = false;
1304 1 : desicDehum.CondenserInletNode = VariableSpeedCoils::GetVSCoilCondenserInletNode(state, desicDehum.CoolingCoilName, ErrorsFound2);
1305 : }
1306 2 : if (desicDehum.CondenserInletNode == 0 && desicDehum.Preheat == Selection::Yes) {
1307 0 : desicDehum.CondenserInletNode =
1308 0 : NodeInputManager::GetOnlySingleNode(state,
1309 0 : desicDehum.CoolingCoilName + " Condenser Inlet Node",
1310 : ErrorsFound,
1311 : DataLoopNode::ConnectionObjectType::DehumidifierDesiccantSystem,
1312 0 : desicDehum.Name,
1313 : DataLoopNode::NodeFluidType::Air,
1314 : DataLoopNode::ConnectionType::OutsideAirReference,
1315 : NodeInputManager::CompFluidStream::Secondary,
1316 : DataLoopNode::ObjectIsNotParent);
1317 0 : OutAirNodeManager::CheckAndAddAirNodeNumber(state, desicDehum.CondenserInletNode, OANodeError);
1318 0 : if (!OANodeError) {
1319 0 : ShowWarningError(state, format("{} \"{}\"", desicDehum.DehumType, desicDehum.Name));
1320 0 : ShowContinueError(state,
1321 0 : format("The {} input is specified as Yes and a condenser air inlet node name was not specified for the "
1322 : "companion cooling coil.",
1323 : cAlphaFields(14)));
1324 0 : ShowContinueError(
1325 0 : state, format("Adding condenser inlet air node for {} \"{}\"", desicDehum.CoolingCoilType, desicDehum.CoolingCoilName));
1326 0 : ShowContinueError(
1327 0 : state, format("...condenser inlet air node name = {}", state.dataLoopNodes->NodeID(desicDehum.CondenserInletNode)));
1328 0 : ShowContinueError(state, "...this node name will be specified as an outdoor air node.");
1329 : }
1330 2 : } else if (desicDehum.Preheat == Selection::Yes) {
1331 2 : if (!OutAirNodeManager::CheckOutAirNodeNumber(state, desicDehum.CondenserInletNode)) {
1332 0 : ShowSevereError(state, format("{} \"{}\"", desicDehum.DehumType, desicDehum.Name));
1333 0 : ShowContinueError(
1334 : state,
1335 0 : format("The regeneration air inlet node must be specified as an outdoor air node when {} is specified as Yes.",
1336 : cAlphaFields(14)));
1337 0 : ErrorsFoundGeneric = true;
1338 : }
1339 : }
1340 : }
1341 :
1342 4 : if (OutAirNodeManager::CheckOutAirNodeNumber(state, desicDehum.RegenAirInNode)) {
1343 2 : desicDehum.RegenInletIsOutsideAirNode = true;
1344 : }
1345 :
1346 4 : if (desicDehum.DXCoilIndex == 0 && desicDehum.Preheat == Selection::Yes) {
1347 0 : ShowWarningError(state, format("{}={}", desicDehum.DehumType, desicDehum.Name));
1348 0 : ShowContinueError(
1349 0 : state, format("A valid {} must be used when condenser waste heat is reclaimed for desiccant regeneration.", cAlphaFields(12)));
1350 0 : ShowContinueError(state, format("... {} = {}", cAlphaFields(11), desicDehum.CoolingCoilType));
1351 0 : ShowContinueError(state, format("... {} = {}", cAlphaFields(12), desicDehum.CoolingCoilName));
1352 0 : ErrorsFoundGeneric = true;
1353 : }
1354 :
1355 4 : if (desicDehum.DXCoilIndex > 0 && desicDehum.CoilUpstreamOfProcessSide == Selection::Yes) {
1356 2 : if ((desicDehum.coolingCoil_TypeNum == HVAC::CoilDX_CoolingSingleSpeed) ||
1357 1 : (desicDehum.coolingCoil_TypeNum == HVAC::CoilDX_CoolingTwoStageWHumControl)) {
1358 1 : ErrorsFound2 = false;
1359 1 : CoilBypassedFlowFrac =
1360 1 : DXCoils::GetDXCoilBypassedFlowFrac(state, desicDehum.CoolingCoilType, desicDehum.CoolingCoilName, ErrorsFound2);
1361 1 : } else if (desicDehum.coolingCoil_TypeNum == HVAC::Coil_CoolingAirToAirVariableSpeed) {
1362 1 : ErrorsFound2 = false;
1363 1 : CoilBypassedFlowFrac = 0.0; // bypass flow fraction not in VS coil model
1364 : }
1365 2 : if (ErrorsFound2) {
1366 0 : ShowContinueError(state, format("...occurs in {} \"{}\"", desicDehum.DehumType, desicDehum.CoolingCoilName));
1367 : }
1368 2 : if (CoilBypassedFlowFrac > 0.0) {
1369 0 : ShowWarningError(state, format("{}={}", desicDehum.DehumType, desicDehum.Name));
1370 0 : ShowContinueError(
1371 : state,
1372 0 : format("A DX coil bypassed air flow fraction greater than 0 may not be used when the input for {} is specified as Yes.",
1373 : cAlphaFields(13)));
1374 0 : ShowContinueError(state,
1375 0 : format("A DX coil with a bypassed air flow fraction greater than 0 may be upstream of the process inlet "
1376 : "however the input for {} must be specified as No.",
1377 : cAlphaFields(13)));
1378 0 : ShowContinueError(state, format("... {} = {}", cAlphaFields(11), desicDehum.CoolingCoilType));
1379 0 : ShowContinueError(state, format("... {} = {}", cAlphaFields(12), desicDehum.CoolingCoilName));
1380 0 : ErrorsFoundGeneric = true;
1381 : }
1382 2 : } else if (desicDehum.DXCoilIndex == 0 && desicDehum.CoilUpstreamOfProcessSide == Selection::Yes) {
1383 0 : ShowSevereError(state, format("{} \"{}\"", desicDehum.DehumType, desicDehum.Name));
1384 0 : ShowContinueError(state, format("A valid companion coil must be specified when {} is specified as Yes.", cAlphaFields(13)));
1385 0 : ErrorsFoundGeneric = true;
1386 : }
1387 :
1388 4 : if (!desicDehum.RegenInletIsOutsideAirNode && desicDehum.Preheat == Selection::Yes) {
1389 0 : ShowWarningError(state, format("{}={}", desicDehum.DehumType, desicDehum.Name));
1390 0 : ShowContinueError(
1391 : state,
1392 0 : format("The desiccant dehumidifier regeneration air inlet must be specified as an outdoor air node when {} is specified as Yes.",
1393 : cAlphaFields(14)));
1394 0 : ShowContinueError(state,
1395 0 : format("... desiccant dehumidifier regeneration air inlet node name = {}",
1396 0 : state.dataLoopNodes->NodeID(desicDehum.RegenAirInNode)));
1397 0 : ErrorsFoundGeneric = true;
1398 : }
1399 :
1400 4 : if (desicDehum.CoilUpstreamOfProcessSide == Selection::Yes) {
1401 2 : if (desicDehum.ProcAirInNode != desicDehum.CoolingCoilOutletNode) {
1402 0 : ShowSevereError(state, format("For {} \"{}\"", desicDehum.DehumType, desicDehum.Name));
1403 0 : ShowContinueError(state, "Node names are inconsistent in companion cooling coil and desiccant heat exchanger objects.");
1404 0 : ShowContinueError(state,
1405 0 : format("For companion cooling coil = {} \"{}\"", desicDehum.CoolingCoilType, desicDehum.CoolingCoilName));
1406 0 : ShowContinueError(
1407 0 : state, format("The outlet node name in cooling coil = {}", state.dataLoopNodes->NodeID(desicDehum.CoolingCoilOutletNode)));
1408 0 : ShowContinueError(state, format("For desiccant heat exchanger = {} \"{}\"", desicDehum.HXType, desicDehum.HXName));
1409 0 : ShowContinueError(state, format("The process air inlet node name = {}", state.dataLoopNodes->NodeID(desicDehum.ProcAirInNode)));
1410 0 : ShowFatalError(state, "...previous error causes program termination.");
1411 : }
1412 : }
1413 :
1414 : // Exhaust Fan input
1415 4 : desicDehum.ExhaustFanMaxVolFlowRate = Numbers(2);
1416 4 : desicDehum.ExhaustFanMaxPower = Numbers(3);
1417 4 : desicDehum.ExhaustFanCurveIndex = Curve::GetCurveIndex(state, Alphas(15));
1418 :
1419 4 : if (desicDehum.ExhaustFanCurveIndex > 0) {
1420 6 : ErrorsFoundGeneric |= EnergyPlus::Curve::CheckCurveDims(state,
1421 : desicDehum.ExhaustFanCurveIndex, // Curve index
1422 : {1}, // Valid dimensions
1423 : RoutineName, // Routine name
1424 : CurrentModuleObject, // Object Type
1425 : desicDehum.Name, // Object Name
1426 2 : cAlphaFields(15)); // Field Name
1427 : }
1428 :
1429 4 : if (desicDehum.Preheat == Selection::Yes) {
1430 2 : ErrorsFound2 = false;
1431 2 : if (desicDehum.ExhaustFanMaxVolFlowRate <= 0) {
1432 0 : ErrorsFound2 = true;
1433 : }
1434 2 : if (desicDehum.ExhaustFanMaxPower <= 0) {
1435 0 : ErrorsFound2 = true;
1436 : }
1437 2 : if (ErrorsFound2) {
1438 0 : ShowSevereError(state, format("{} \"{}\"", desicDehum.DehumType, desicDehum.Name));
1439 0 : ShowContinueError(
1440 0 : state, format("{} and {} must be defined if {} field is \"Yes\".", cNumericFields(2), cNumericFields(3), cAlphaFields(14)));
1441 : }
1442 2 : } else if (desicDehum.Preheat == Selection::No) {
1443 2 : if (desicDehum.ExhaustFanMaxVolFlowRate > 0.0) {
1444 0 : ShowWarningError(state, format("{} \"{}\"", desicDehum.DehumType, desicDehum.Name));
1445 0 : ShowContinueError(state, format("{} should be 0 if {} field is \"No\".", cNumericFields(2), cAlphaFields(14)));
1446 0 : ShowContinueError(state, format("...{} will not be used and is reset to 0.", cNumericFields(2)));
1447 0 : desicDehum.ExhaustFanMaxVolFlowRate = 0.0;
1448 : }
1449 : }
1450 4 : }
1451 :
1452 : // SET UP OUTPUTS
1453 12 : for (int DesicDehumNum = 1; DesicDehumNum <= state.dataDesiccantDehumidifiers->NumSolidDesicDehums; ++DesicDehumNum) {
1454 5 : auto &desicDehum = state.dataDesiccantDehumidifiers->DesicDehum(DesicDehumNum);
1455 : // Setup Report variables for the Desiccant Dehumidifiers
1456 10 : SetupOutputVariable(state,
1457 : "Dehumidifier Removed Water Mass",
1458 : Constant::Units::kg,
1459 5 : desicDehum.WaterRemove,
1460 : OutputProcessor::TimeStepType::System,
1461 : OutputProcessor::StoreType::Sum,
1462 5 : desicDehum.Name);
1463 10 : SetupOutputVariable(state,
1464 : "Dehumidifier Removed Water Mass Flow Rate",
1465 : Constant::Units::kg_s,
1466 5 : desicDehum.WaterRemoveRate,
1467 : OutputProcessor::TimeStepType::System,
1468 : OutputProcessor::StoreType::Average,
1469 5 : desicDehum.Name);
1470 10 : SetupOutputVariable(state,
1471 : "Dehumidifier Part Load Ratio",
1472 : Constant::Units::None,
1473 5 : desicDehum.PartLoad,
1474 : OutputProcessor::TimeStepType::System,
1475 : OutputProcessor::StoreType::Average,
1476 5 : desicDehum.Name);
1477 10 : SetupOutputVariable(state,
1478 : "Dehumidifier Electricity Rate",
1479 : Constant::Units::W,
1480 5 : desicDehum.ElecUseRate,
1481 : OutputProcessor::TimeStepType::System,
1482 : OutputProcessor::StoreType::Average,
1483 5 : desicDehum.Name);
1484 10 : SetupOutputVariable(state,
1485 : "Dehumidifier Electricity Energy",
1486 : Constant::Units::J,
1487 5 : desicDehum.ElecUseEnergy,
1488 : OutputProcessor::TimeStepType::System,
1489 : OutputProcessor::StoreType::Sum,
1490 5 : desicDehum.Name,
1491 : Constant::eResource::Electricity,
1492 : OutputProcessor::Group::HVAC,
1493 : OutputProcessor::EndUseCat::Cooling);
1494 10 : SetupOutputVariable(state,
1495 : "Dehumidifier Regeneration Specific Energy",
1496 : Constant::Units::J_kgWater,
1497 5 : desicDehum.SpecRegenEnergy,
1498 : OutputProcessor::TimeStepType::System,
1499 : OutputProcessor::StoreType::Average,
1500 5 : desicDehum.Name);
1501 10 : SetupOutputVariable(state,
1502 : "Dehumidifier Regeneration Rate",
1503 : Constant::Units::W,
1504 5 : desicDehum.QRegen,
1505 : OutputProcessor::TimeStepType::System,
1506 : OutputProcessor::StoreType::Average,
1507 5 : desicDehum.Name);
1508 10 : SetupOutputVariable(state,
1509 : "Dehumidifier Regeneration Energy",
1510 : Constant::Units::J,
1511 5 : desicDehum.RegenEnergy,
1512 : OutputProcessor::TimeStepType::System,
1513 : OutputProcessor::StoreType::Sum,
1514 5 : desicDehum.Name);
1515 10 : SetupOutputVariable(state,
1516 : "Dehumidifier Regeneration Air Speed",
1517 : Constant::Units::m_s,
1518 5 : desicDehum.RegenAirVel,
1519 : OutputProcessor::TimeStepType::System,
1520 : OutputProcessor::StoreType::Average,
1521 5 : desicDehum.Name);
1522 10 : SetupOutputVariable(state,
1523 : "Dehumidifier Regeneration Air Mass Flow Rate",
1524 : Constant::Units::kg_s,
1525 5 : desicDehum.RegenAirInMassFlowRate,
1526 : OutputProcessor::TimeStepType::System,
1527 : OutputProcessor::StoreType::Average,
1528 5 : desicDehum.Name);
1529 10 : SetupOutputVariable(state,
1530 : "Dehumidifier Process Air Mass Flow Rate",
1531 : Constant::Units::kg_s,
1532 5 : desicDehum.ProcAirInMassFlowRate,
1533 : OutputProcessor::TimeStepType::System,
1534 : OutputProcessor::StoreType::Average,
1535 5 : desicDehum.Name);
1536 : }
1537 :
1538 11 : for (int DesicDehumIndex = 1; DesicDehumIndex <= state.dataDesiccantDehumidifiers->NumGenericDesicDehums; ++DesicDehumIndex) {
1539 : // this is wrong, should be a loop from (state.dataDesiccantDehumidifiers->NumSolidDesicDehums + 1) to
1540 : // (state.dataDesiccantDehumidifiers->NumDesicDehums = NumSolidDesicDehums + NumGenericDesicDehums)
1541 : // DesicDehumNum = DesicDehumIndex + state.dataDesiccantDehumidifiers->NumSolidDesicDehums;
1542 4 : auto &desicDehum = state.dataDesiccantDehumidifiers->DesicDehum(DesicDehumIndex);
1543 : // Setup Report variables for the Desiccant Dehumidifiers
1544 8 : SetupOutputVariable(state,
1545 : "Dehumidifier Removed Water Mass",
1546 : Constant::Units::kg,
1547 4 : desicDehum.WaterRemove,
1548 : OutputProcessor::TimeStepType::System,
1549 : OutputProcessor::StoreType::Sum,
1550 4 : desicDehum.Name);
1551 8 : SetupOutputVariable(state,
1552 : "Dehumidifier Removed Water Mass Flow Rate",
1553 : Constant::Units::kg_s,
1554 4 : desicDehum.WaterRemoveRate,
1555 : OutputProcessor::TimeStepType::System,
1556 : OutputProcessor::StoreType::Average,
1557 4 : desicDehum.Name);
1558 8 : SetupOutputVariable(state,
1559 : "Dehumidifier Part Load Ratio",
1560 : Constant::Units::None,
1561 4 : desicDehum.PartLoad,
1562 : OutputProcessor::TimeStepType::System,
1563 : OutputProcessor::StoreType::Average,
1564 4 : desicDehum.Name);
1565 4 : if (desicDehum.ExhaustFanMaxVolFlowRate > 0) {
1566 4 : SetupOutputVariable(state,
1567 : "Dehumidifier Exhaust Fan Electricity Rate",
1568 : Constant::Units::W,
1569 2 : desicDehum.ExhaustFanPower,
1570 : OutputProcessor::TimeStepType::System,
1571 : OutputProcessor::StoreType::Average,
1572 2 : desicDehum.Name);
1573 4 : SetupOutputVariable(state,
1574 : "Dehumidifier Exhaust Fan Electricity Energy",
1575 : Constant::Units::J,
1576 2 : desicDehum.ExhaustFanElecConsumption,
1577 : OutputProcessor::TimeStepType::System,
1578 : OutputProcessor::StoreType::Sum,
1579 2 : desicDehum.Name,
1580 : Constant::eResource::Electricity,
1581 : OutputProcessor::Group::HVAC,
1582 : OutputProcessor::EndUseCat::Cooling);
1583 : }
1584 : }
1585 :
1586 7 : if (ErrorsFound) {
1587 0 : ShowFatalError(state, "Errors found in getting Dehumidifier:Desiccant:NoFans input");
1588 7 : } else if (ErrorsFoundGeneric) {
1589 0 : ShowFatalError(state, "Errors found in getting DESICCANT DEHUMIDIFIER input");
1590 : }
1591 :
1592 7 : Alphas.deallocate();
1593 7 : cAlphaFields.deallocate();
1594 7 : cNumericFields.deallocate();
1595 7 : Numbers.deallocate();
1596 7 : lAlphaBlanks.deallocate();
1597 7 : lNumericBlanks.deallocate();
1598 7 : }
1599 :
1600 283978 : void InitDesiccantDehumidifier(EnergyPlusData &state,
1601 : int const DesicDehumNum, // number of the current dehumidifier being simulated
1602 : bool const FirstHVACIteration // TRUE if 1st HVAC simulation of system timestep
1603 : )
1604 : {
1605 :
1606 : // SUBROUTINE INFORMATION:
1607 : // AUTHOR Michael J. Witte, GARD Analytics, Inc.
1608 : // for Gas Research Institute
1609 : // DATE WRITTEN March 2001
1610 : // MODIFIED Jan 2005 M. J. Witte, GARD Analytics, Inc.
1611 : // Add setpoint validation for new control type option:
1612 : // NODE LEAVING HUMRAT SETPOINT:BYPASS
1613 : // Work supported by ASHRAE research project 1254-RP
1614 : // June 2007 R. Raustad, FSEC
1615 : // Added new dehumidifier type -- DESICCANT DEHUMIDIFIER
1616 : // May 2009, B. Griffith, NREL. added EMS node setpoint checks
1617 :
1618 : // PURPOSE OF THIS SUBROUTINE:
1619 : // This subroutine is for initializations of the dehumidifier Components.
1620 :
1621 : // METHODOLOGY EMPLOYED:
1622 : // Uses the status flags to trigger initializations.
1623 :
1624 : // SUBROUTINE PARAMETER DEFINITIONS:
1625 : static constexpr std::string_view RoutineName("InitDesiccantDehumidifier");
1626 283992 : static std::string const initCBVAV("InitCBVAV");
1627 :
1628 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1629 : // bool ErrorsFound(false); // Set to true if errors in input, fatal at end of routine
1630 : Real64 QCoilActual; // actual CBVAV steam heating coil load met (W)
1631 : bool ErrorFlag; // local error flag returned from data mining
1632 283978 : bool DoSetPointTest = state.dataHVACGlobal->DoSetPointTest;
1633 :
1634 283978 : auto &desicDehum = state.dataDesiccantDehumidifiers->DesicDehum(DesicDehumNum);
1635 :
1636 283978 : if (state.dataDesiccantDehumidifiers->InitDesiccantDehumidifierOneTimeFlag) {
1637 :
1638 : // initialize the environment and sizing flags
1639 7 : state.dataDesiccantDehumidifiers->MyEnvrnFlag.dimension(state.dataDesiccantDehumidifiers->NumDesicDehums, true);
1640 7 : state.dataDesiccantDehumidifiers->MyPlantScanFlag.dimension(state.dataDesiccantDehumidifiers->NumDesicDehums, true);
1641 :
1642 7 : state.dataDesiccantDehumidifiers->InitDesiccantDehumidifierOneTimeFlag = false;
1643 : }
1644 :
1645 283978 : if (state.dataDesiccantDehumidifiers->MyPlantScanFlag(DesicDehumNum) && allocated(state.dataPlnt->PlantLoop)) {
1646 9 : if ((desicDehum.RegenCoilType_Num == HVAC::Coil_HeatingWater) || (desicDehum.RegenCoilType_Num == HVAC::Coil_HeatingSteam)) {
1647 0 : if (desicDehum.RegenCoilType_Num == HVAC::Coil_HeatingWater) {
1648 0 : ErrorFlag = false;
1649 0 : PlantUtilities::ScanPlantLoopsForObject(state,
1650 : desicDehum.RegenCoilName,
1651 : DataPlant::PlantEquipmentType::CoilWaterSimpleHeating,
1652 0 : desicDehum.plantLoc,
1653 : ErrorFlag,
1654 : _,
1655 : _,
1656 : _,
1657 : _,
1658 : _);
1659 0 : if (ErrorFlag) {
1660 0 : ShowFatalError(state, "InitDesiccantDehumidifier: Program terminated for previous conditions.");
1661 : }
1662 :
1663 0 : ErrorFlag = false;
1664 0 : desicDehum.MaxCoilFluidFlow =
1665 0 : WaterCoils::GetCoilMaxWaterFlowRate(state, "Coil:Heating:Water", desicDehum.RegenCoilName, ErrorFlag);
1666 0 : if (desicDehum.MaxCoilFluidFlow > 0.0) {
1667 : Real64 FluidDensity =
1668 0 : state.dataPlnt->PlantLoop(desicDehum.plantLoc.loopNum).glycol->getDensity(state, Constant::HWInitConvTemp, initCBVAV);
1669 0 : desicDehum.MaxCoilFluidFlow *= FluidDensity;
1670 : }
1671 :
1672 0 : } else if (desicDehum.RegenCoilType_Num == HVAC::Coil_HeatingSteam) {
1673 :
1674 0 : ErrorFlag = false;
1675 0 : PlantUtilities::ScanPlantLoopsForObject(state,
1676 : desicDehum.RegenCoilName,
1677 : DataPlant::PlantEquipmentType::CoilSteamAirHeating,
1678 0 : desicDehum.plantLoc,
1679 : ErrorFlag,
1680 : _,
1681 : _,
1682 : _,
1683 : _,
1684 : _);
1685 :
1686 0 : if (ErrorFlag) {
1687 0 : ShowFatalError(state, "InitDesiccantDehumidifier: Program terminated for previous conditions.");
1688 : }
1689 0 : ErrorFlag = false;
1690 0 : desicDehum.MaxCoilFluidFlow = SteamCoils::GetCoilMaxSteamFlowRate(state, desicDehum.RegenCoilIndex, ErrorFlag);
1691 :
1692 0 : if (desicDehum.MaxCoilFluidFlow > 0.0) {
1693 0 : Real64 FluidDensity = Fluid::GetSteam(state)->getSatDensity(state, TempSteamIn, 1.0, RoutineName);
1694 0 : desicDehum.MaxCoilFluidFlow *= FluidDensity;
1695 : }
1696 : }
1697 :
1698 : // fill outlet node for regenartion hot water or steam heating coil
1699 0 : desicDehum.CoilOutletNode = DataPlant::CompData::getPlantComponent(state, desicDehum.plantLoc).NodeNumOut;
1700 0 : state.dataDesiccantDehumidifiers->MyPlantScanFlag(DesicDehumNum) = false;
1701 :
1702 0 : } else { // DesicDehum is not connected to plant
1703 9 : state.dataDesiccantDehumidifiers->MyPlantScanFlag(DesicDehumNum) = false;
1704 : }
1705 283969 : } else if (state.dataDesiccantDehumidifiers->MyPlantScanFlag(DesicDehumNum) && !state.dataGlobal->AnyPlantInModel) {
1706 0 : state.dataDesiccantDehumidifiers->MyPlantScanFlag(DesicDehumNum) = false;
1707 : }
1708 :
1709 283978 : switch (desicDehum.DehumTypeCode) {
1710 92320 : case DesicDehumType::Solid: {
1711 92320 : if (!state.dataGlobal->SysSizingCalc && state.dataDesiccantDehumidifiers->MySetPointCheckFlag && DoSetPointTest) {
1712 5 : if (desicDehum.controlType == DesicDehumCtrlType::NodeHumratBypass) {
1713 2 : int ControlNode = desicDehum.ProcAirOutNode;
1714 2 : if (ControlNode > 0) {
1715 2 : if (state.dataLoopNodes->Node(ControlNode).HumRatMax == DataLoopNode::SensedNodeFlagValue) {
1716 0 : if (!state.dataGlobal->AnyEnergyManagementSystemInModel) {
1717 0 : ShowSevereError(state, "Missing humidity ratio setpoint (HumRatMax) for ");
1718 0 : ShowContinueError(state, format("Dehumidifier:Desiccant:NoFans: {}", desicDehum.Name));
1719 0 : ShowContinueError(state, format("Node Referenced={}", state.dataLoopNodes->NodeID(ControlNode)));
1720 0 : ShowContinueError(state, "use a Setpoint Manager to establish a setpoint at the process air outlet node.");
1721 0 : state.dataHVACGlobal->SetPointErrorFlag = true;
1722 : } else {
1723 0 : EMSManager::CheckIfNodeSetPointManagedByEMS(
1724 0 : state, ControlNode, HVAC::CtrlVarType::MaxHumRat, state.dataHVACGlobal->SetPointErrorFlag);
1725 0 : if (state.dataHVACGlobal->SetPointErrorFlag) {
1726 0 : ShowSevereError(state, "Missing humidity ratio setpoint (HumRatMax) for ");
1727 0 : ShowContinueError(state, format("Dehumidifier:Desiccant:NoFans: {}", desicDehum.Name));
1728 0 : ShowContinueError(state, format("Node Referenced={}", state.dataLoopNodes->NodeID(ControlNode)));
1729 0 : ShowContinueError(state, "use a Setpoint Manager to establish a setpoint at the process air outlet node.");
1730 0 : ShowContinueError(state, "Or use EMS Actuator to establish a setpoint at the process air outlet node.");
1731 : }
1732 : }
1733 : }
1734 : }
1735 : }
1736 5 : state.dataDesiccantDehumidifiers->MySetPointCheckFlag = false;
1737 : }
1738 : // always do these initializations every iteration
1739 92320 : int ProcInNode = desicDehum.ProcAirInNode;
1740 92320 : desicDehum.ProcAirInTemp = state.dataLoopNodes->Node(ProcInNode).Temp;
1741 92320 : desicDehum.ProcAirInHumRat = state.dataLoopNodes->Node(ProcInNode).HumRat;
1742 92320 : desicDehum.ProcAirInEnthalpy = state.dataLoopNodes->Node(ProcInNode).Enthalpy;
1743 92320 : desicDehum.ProcAirInMassFlowRate = state.dataLoopNodes->Node(ProcInNode).MassFlowRate;
1744 :
1745 : // Determine heating coil inlet conditions by calling it with zero load
1746 : // Not sure if this is really a good way to do this, should revisit for next release.
1747 92320 : CalcNonDXHeatingCoils(state, DesicDehumNum, FirstHVACIteration, 0.0);
1748 :
1749 92320 : int RegenInNode = desicDehum.RegenAirInNode;
1750 92320 : desicDehum.RegenAirInTemp = state.dataLoopNodes->Node(RegenInNode).Temp;
1751 92320 : desicDehum.RegenAirInHumRat = state.dataLoopNodes->Node(RegenInNode).HumRat;
1752 92320 : desicDehum.RegenAirInEnthalpy = state.dataLoopNodes->Node(RegenInNode).Enthalpy;
1753 :
1754 92320 : desicDehum.WaterRemove = 0.0;
1755 92320 : desicDehum.ElecUseEnergy = 0.0;
1756 92320 : desicDehum.ElecUseRate = 0.0;
1757 :
1758 92320 : } break;
1759 191658 : case DesicDehumType::Generic: {
1760 : // Do the Begin Environment initializations
1761 191658 : if (state.dataGlobal->BeginEnvrnFlag && state.dataDesiccantDehumidifiers->MyEnvrnFlag(DesicDehumNum)) {
1762 : // Change the Volume Flow Rates to Mass Flow Rates
1763 4 : desicDehum.ExhaustFanMaxMassFlowRate = desicDehum.ExhaustFanMaxVolFlowRate * state.dataEnvrn->StdRhoAir;
1764 :
1765 : // set fluid-side hardware limits
1766 4 : if (desicDehum.CoilControlNode > 0) {
1767 : // If water coil max water flow rate is autosized, simulate once in order to mine max water flow rate
1768 0 : if (desicDehum.MaxCoilFluidFlow == DataSizing::AutoSize) {
1769 0 : if (desicDehum.RegenCoilType_Num == HVAC::Coil_HeatingWater) {
1770 0 : WaterCoils::SimulateWaterCoilComponents(state, desicDehum.RegenCoilName, FirstHVACIteration, desicDehum.RegenCoilIndex);
1771 0 : ErrorFlag = false;
1772 : Real64 CoilMaxVolFlowRate =
1773 0 : WaterCoils::GetCoilMaxWaterFlowRate(state, "Coil:Heating:Water", desicDehum.RegenCoilName, ErrorFlag);
1774 : // if (ErrorFlag) {
1775 : // ErrorsFound = true;
1776 : //}
1777 0 : if (CoilMaxVolFlowRate != DataSizing::AutoSize) {
1778 0 : Real64 FluidDensity = state.dataPlnt->PlantLoop(desicDehum.plantLoc.loopNum)
1779 0 : .glycol->getDensity(state, Constant::HWInitConvTemp, RoutineName);
1780 0 : desicDehum.MaxCoilFluidFlow = CoilMaxVolFlowRate * FluidDensity;
1781 : }
1782 : }
1783 0 : if (desicDehum.RegenCoilType_Num == HVAC::Coil_HeatingSteam) {
1784 0 : SteamCoils::SimulateSteamCoilComponents(state,
1785 : desicDehum.RegenCoilName,
1786 : FirstHVACIteration,
1787 0 : desicDehum.RegenCoilIndex,
1788 0 : 1.0,
1789 : QCoilActual); // simulate any load > 0 to get max capacity of steam coil
1790 0 : ErrorFlag = false;
1791 0 : Real64 CoilMaxVolFlowRate = SteamCoils::GetCoilMaxSteamFlowRate(state, desicDehum.RegenCoilIndex, ErrorFlag);
1792 : // if (ErrorFlag) {
1793 : // ErrorsFound = true;
1794 : //}
1795 0 : if (CoilMaxVolFlowRate != DataSizing::AutoSize) {
1796 0 : Real64 FluidDensity = Fluid::GetSteam(state)->getSatDensity(state, TempSteamIn, 1.0, RoutineName);
1797 0 : desicDehum.MaxCoilFluidFlow = CoilMaxVolFlowRate * FluidDensity;
1798 : }
1799 : }
1800 : }
1801 0 : PlantUtilities::InitComponentNodes(
1802 : state, 0.0, desicDehum.MaxCoilFluidFlow, desicDehum.CoilControlNode, desicDehum.CoilOutletNode);
1803 : }
1804 :
1805 4 : state.dataDesiccantDehumidifiers->MyEnvrnFlag(DesicDehumNum) = false;
1806 : }
1807 :
1808 191658 : if (!state.dataGlobal->SysSizingCalc && state.dataDesiccantDehumidifiers->MySetPointCheckFlag && DoSetPointTest) {
1809 2 : int ControlNode = desicDehum.ControlNodeNum;
1810 2 : if (ControlNode > 0) {
1811 2 : if (state.dataLoopNodes->Node(ControlNode).HumRatMax == DataLoopNode::SensedNodeFlagValue) {
1812 0 : if (!state.dataGlobal->AnyEnergyManagementSystemInModel) {
1813 0 : ShowSevereError(state, "Missing maximum humidity ratio setpoint (MaxHumRat) for ");
1814 0 : ShowContinueError(state, format("{}: {}", desicDehum.DehumType, desicDehum.Name));
1815 0 : ShowContinueError(state, format("Node Referenced={}", state.dataLoopNodes->NodeID(ControlNode)));
1816 0 : ShowContinueError(state, "use a Setpoint Manager to establish a \"MaxHumRat\" setpoint at the process air control node.");
1817 0 : state.dataHVACGlobal->SetPointErrorFlag = true;
1818 : } else {
1819 0 : EMSManager::CheckIfNodeSetPointManagedByEMS(
1820 0 : state, ControlNode, HVAC::CtrlVarType::MaxHumRat, state.dataHVACGlobal->SetPointErrorFlag);
1821 0 : if (state.dataHVACGlobal->SetPointErrorFlag) {
1822 0 : ShowSevereError(state, "Missing maximum humidity ratio setpoint (MaxHumRat) for ");
1823 0 : ShowContinueError(state, format("{}: {}", desicDehum.DehumType, desicDehum.Name));
1824 0 : ShowContinueError(state, format("Node Referenced={}", state.dataLoopNodes->NodeID(ControlNode)));
1825 0 : ShowContinueError(state,
1826 : "use a Setpoint Manager to establish a \"MaxHumRat\" setpoint at the process air control node.");
1827 0 : ShowContinueError(state, "Or use EMS Actuator to establish a setpoint at the process air outlet node.");
1828 : }
1829 : }
1830 : }
1831 : }
1832 2 : state.dataDesiccantDehumidifiers->MySetPointCheckFlag = false;
1833 : }
1834 191658 : int RegenInNode = desicDehum.RegenAirInNode;
1835 191658 : desicDehum.RegenAirInTemp = state.dataLoopNodes->Node(RegenInNode).Temp;
1836 191658 : desicDehum.RegenAirInMassFlowRate = state.dataLoopNodes->Node(RegenInNode).MassFlowRate;
1837 :
1838 191658 : desicDehum.ExhaustFanPower = 0.0;
1839 191658 : desicDehum.WaterRemoveRate = 0.0;
1840 191658 : } break;
1841 0 : default:
1842 0 : break;
1843 : }
1844 283978 : }
1845 :
1846 283978 : void ControlDesiccantDehumidifier(EnergyPlusData &state,
1847 : int const DesicDehumNum, // number of the current dehumidifier being simulated
1848 : Real64 &HumRatNeeded, // process air leaving humidity ratio set by controller [kg water/kg air]
1849 : [[maybe_unused]] bool const FirstHVACIteration // TRUE if 1st HVAC simulation of system timestep !unused1208
1850 : )
1851 : {
1852 :
1853 : // SUBROUTINE INFORMATION:
1854 : // AUTHOR Michael J. Witte, GARD Analytics, Inc.
1855 : // for Gas Research Institute
1856 : // DATE WRITTEN March 2001
1857 : // MODIFIED Jan 2005 M. J. Witte, GARD Analytics, Inc.
1858 : // Add new control type option:
1859 : // NODE LEAVING HUMRAT SETPOINT:BYPASS
1860 : // Change existing control type to:
1861 : // FIXED LEAVING HUMRAT SETPOINT:BYPASS
1862 : // Work supported by ASHRAE research project 1254-RP
1863 : // June 2007 R. Raustad, FSEC
1864 : // Added new dehumidifier type -- DESICCANT DEHUMIDIFIER
1865 :
1866 : // PURPOSE OF THIS SUBROUTINE:
1867 : // This subroutine sets the output required from the dehumidifier
1868 :
1869 : // METHODOLOGY EMPLOYED:
1870 : // Uses a maximum humidity ratio setpoint to calculate required process
1871 : // leaving humidity ratio
1872 :
1873 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1874 : Real64 ProcAirMassFlowRate; // process air mass flow rate [kg/s]
1875 : Real64 RegenAirMassFlowRate; // regen air mass flow rate [kg/s]
1876 :
1877 283978 : auto &desicDehum = state.dataDesiccantDehumidifiers->DesicDehum(DesicDehumNum);
1878 :
1879 283978 : ProcAirMassFlowRate = 0.0;
1880 283978 : RegenAirMassFlowRate = 0.0;
1881 283978 : bool UnitOn = true;
1882 :
1883 283978 : switch (desicDehum.DehumTypeCode) {
1884 92320 : case DesicDehumType::Solid: {
1885 92320 : if (desicDehum.HumRatSet <= 0.0) {
1886 0 : UnitOn = false;
1887 : }
1888 92320 : ProcAirMassFlowRate = desicDehum.ProcAirInMassFlowRate;
1889 92320 : if (ProcAirMassFlowRate <= HVAC::SmallMassFlow) {
1890 54 : UnitOn = false;
1891 : }
1892 :
1893 92320 : if (desicDehum.availSched->getCurrentVal() <= 0.0) {
1894 4446 : UnitOn = false;
1895 : }
1896 :
1897 : // If incoming conditions are outside valid range for curve fits, then shut unit off, do not issue warnings
1898 :
1899 92320 : if (UnitOn) {
1900 87874 : if ((desicDehum.ProcAirInTemp < desicDehum.MinProcAirInTemp) || (desicDehum.ProcAirInTemp > desicDehum.MaxProcAirInTemp)) {
1901 31524 : UnitOn = false;
1902 : }
1903 87874 : if ((desicDehum.ProcAirInHumRat < desicDehum.MinProcAirInHumRat) || (desicDehum.ProcAirInHumRat > desicDehum.MaxProcAirInHumRat)) {
1904 31524 : UnitOn = false;
1905 : }
1906 : }
1907 :
1908 92320 : if (UnitOn) {
1909 :
1910 : // perform the correct dehumidifier control strategy
1911 56350 : switch (desicDehum.controlType) {
1912 23182 : case DesicDehumCtrlType::FixedHumratBypass: {
1913 23182 : HumRatNeeded = desicDehum.HumRatSet;
1914 23182 : if (HumRatNeeded <= 0.0) {
1915 0 : ShowSevereError(state, format("Dehumidifier:Desiccant:NoFans: {}", desicDehum.Name));
1916 0 : ShowContinueError(state, format("Invalid Leaving Max Humidity Ratio Setpoint={:.8T}", HumRatNeeded));
1917 0 : ShowFatalError(state, "must be > 0.0");
1918 : }
1919 23182 : } break;
1920 33168 : case DesicDehumCtrlType::NodeHumratBypass: {
1921 33168 : HumRatNeeded = state.dataLoopNodes->Node(desicDehum.ProcAirOutNode).HumRatMax;
1922 33168 : } break;
1923 0 : default: {
1924 0 : ShowFatalError(state, format("Invalid control type in desiccant dehumidifier = {}", desicDehum.Name));
1925 0 : } break;
1926 : }
1927 :
1928 : // Setpoint of zero indicates no load from setpoint manager max hum
1929 56350 : if ((HumRatNeeded == 0.0) || (desicDehum.ProcAirInHumRat <= HumRatNeeded)) {
1930 348 : HumRatNeeded = desicDehum.ProcAirInHumRat;
1931 : }
1932 : } else {
1933 35970 : HumRatNeeded = desicDehum.ProcAirInHumRat;
1934 : }
1935 :
1936 92320 : } break;
1937 191658 : case DesicDehumType::Generic: {
1938 191658 : ProcAirMassFlowRate = state.dataLoopNodes->Node(desicDehum.ProcAirInNode).MassFlowRate;
1939 191658 : if (ProcAirMassFlowRate <= HVAC::SmallMassFlow) {
1940 18 : UnitOn = false;
1941 : }
1942 :
1943 191658 : if (desicDehum.availSched->getCurrentVal() <= 0.0) {
1944 0 : UnitOn = false;
1945 : }
1946 :
1947 191658 : if (UnitOn) {
1948 191640 : if (desicDehum.ControlNodeNum == desicDehum.ProcAirOutNode) {
1949 191640 : HumRatNeeded = state.dataLoopNodes->Node(desicDehum.ControlNodeNum).HumRatMax;
1950 : } else {
1951 0 : if (state.dataLoopNodes->Node(desicDehum.ControlNodeNum).HumRatMax > 0.0) {
1952 0 : HumRatNeeded = state.dataLoopNodes->Node(desicDehum.ControlNodeNum).HumRatMax -
1953 0 : (state.dataLoopNodes->Node(desicDehum.ControlNodeNum).HumRat -
1954 0 : state.dataLoopNodes->Node(desicDehum.ProcAirOutNode).HumRat);
1955 : } else {
1956 0 : HumRatNeeded = 0.0;
1957 : }
1958 : }
1959 :
1960 : // Setpoint of zero indicates no load from setpoint manager max hum
1961 191640 : if ((HumRatNeeded == 0.0) || (state.dataLoopNodes->Node(desicDehum.ProcAirInNode).HumRat <= HumRatNeeded)) {
1962 187437 : HumRatNeeded = state.dataLoopNodes->Node(desicDehum.ProcAirInNode).HumRat;
1963 : }
1964 : } else {
1965 18 : HumRatNeeded = state.dataLoopNodes->Node(desicDehum.ProcAirInNode).HumRat;
1966 : }
1967 :
1968 191658 : } break;
1969 0 : default:
1970 0 : break;
1971 : }
1972 283978 : }
1973 :
1974 92320 : void CalcSolidDesiccantDehumidifier(EnergyPlusData &state,
1975 : int const DesicDehumNum, // number of the current dehumidifier being simulated
1976 : Real64 const HumRatNeeded, // process air leaving humidity ratio set by controller [kgWater/kgDryAir]
1977 : bool const FirstHVACIteration // TRUE if 1st HVAC simulation of system timestep
1978 : )
1979 : {
1980 :
1981 : // SUBROUTINE INFORMATION:
1982 : // AUTHOR Michael J. Witte, GARD Analytics, Inc.
1983 : // for Gas Research Institute
1984 : // DATE WRITTEN March 2001
1985 :
1986 : // PURPOSE OF THIS SUBROUTINE:
1987 : // Calculate the electricity consumption, regen heat requirements and the outlet
1988 : // conditions for a solid desiccant dehumidifier, given the inlet conditions and
1989 : // and the needed process leaving humidity ratio.
1990 :
1991 : // METHODOLOGY EMPLOYED:
1992 : // Given the entering conditions, the full-load outlet conditions are calculated.
1993 : // Adjust for part-load if required.
1994 : // Caclulate required regen energy and call regen coil and regen fan.
1995 : // Desiccant wheel leaving conditions and regen energy requirements are calculated
1996 : // from empirical curve fits. The user can select either default built-in
1997 : // performance curves, or use custom user-defined curves.
1998 :
1999 : // REFERENCES:
2000 : // The default performance curves represent a commerical-grade solid desiccant
2001 : // wheel typical of HVAC applications in the early 1990's. These curves were
2002 : // developed for Gas Research Institute by William W. Worek, University of Illinois
2003 : // at Chicago.
2004 :
2005 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
2006 :
2007 : Real64 ProcAirOutHumRat; // process outlet air humidity ratio [kgWater/kgDryAir]
2008 : Real64 ProcAirOutTemp; // process outlet air temperature [C]
2009 : Real64 QRegen; // regen heat input rate requested from regen coil [W]
2010 : Real64 QDelivered; // regen heat actually delivered by regen coil [W]
2011 : // REAL(r64) :: RegenAirInHumRat ! regen inlet air humidity ratio [kgWater/kgDryAir]
2012 : Real64 RegenAirVel; // regen air velocity [m/s]
2013 : Real64 RegenAirMassFlowRate; // regen air mass flow rate [kg/s]
2014 : Real64 SpecRegenEnergy; // specific regen energy [J/kg of water removed]
2015 : Real64 ElecUseRate; // electricity consumption rate [W]
2016 :
2017 : // Variables for hardwired coefficients for default performance model
2018 :
2019 : Real64 TC0;
2020 : Real64 TC1;
2021 : Real64 TC2;
2022 : Real64 TC3;
2023 : Real64 TC4;
2024 : Real64 TC5;
2025 : Real64 TC6;
2026 : Real64 TC7;
2027 : Real64 TC8;
2028 : Real64 TC9;
2029 : Real64 TC10;
2030 : Real64 TC11;
2031 : Real64 TC12;
2032 : Real64 TC13;
2033 : Real64 TC14;
2034 : Real64 TC15;
2035 :
2036 : Real64 WC0;
2037 : Real64 WC1;
2038 : Real64 WC2;
2039 : Real64 WC3;
2040 : Real64 WC4;
2041 : Real64 WC5;
2042 : Real64 WC6;
2043 : Real64 WC7;
2044 : Real64 WC8;
2045 : Real64 WC9;
2046 : Real64 WC10;
2047 : Real64 WC11;
2048 : Real64 WC12;
2049 : Real64 WC13;
2050 : Real64 WC14;
2051 : Real64 WC15;
2052 :
2053 : Real64 QC0;
2054 : Real64 QC1;
2055 : Real64 QC2;
2056 : Real64 QC3;
2057 : Real64 QC4;
2058 : Real64 QC5;
2059 : Real64 QC6;
2060 : Real64 QC7;
2061 : Real64 QC8;
2062 : Real64 QC9;
2063 : Real64 QC10;
2064 : Real64 QC11;
2065 : Real64 QC12;
2066 : Real64 QC13;
2067 : Real64 QC14;
2068 : Real64 QC15;
2069 :
2070 : Real64 RC0;
2071 : Real64 RC1;
2072 : Real64 RC2;
2073 : Real64 RC3;
2074 : Real64 RC4;
2075 : Real64 RC5;
2076 : Real64 RC6;
2077 : Real64 RC7;
2078 : Real64 RC8;
2079 : Real64 RC9;
2080 : Real64 RC10;
2081 : Real64 RC11;
2082 : Real64 RC12;
2083 : Real64 RC13;
2084 : Real64 RC14;
2085 : Real64 RC15;
2086 :
2087 92320 : auto &desicDehum = state.dataDesiccantDehumidifiers->DesicDehum(DesicDehumNum);
2088 :
2089 : // Setup internal variables for calculations
2090 :
2091 92320 : Real64 ProcAirInTemp = desicDehum.ProcAirInTemp;
2092 92320 : Real64 ProcAirInHumRat = desicDehum.ProcAirInHumRat;
2093 92320 : Real64 ProcAirMassFlowRate = desicDehum.ProcAirInMassFlowRate;
2094 92320 : Real64 ProcAirVel = desicDehum.NomProcAirVel;
2095 92320 : Real64 PartLoad = 0.0;
2096 :
2097 92320 : Real64 RegenAirInTemp = desicDehum.RegenAirInTemp;
2098 92320 : Real64 NomRegenTemp = desicDehum.NomRegenTemp;
2099 :
2100 : // Calculate min available process out humrat
2101 92320 : bool UnitOn = false;
2102 92320 : Real64 MinProcAirOutHumRat = 0.0; // MAX(MinProcAirOutHumRat,0.000857)
2103 :
2104 92320 : if (HumRatNeeded < ProcAirInHumRat) {
2105 :
2106 56002 : UnitOn = true;
2107 :
2108 56002 : switch (desicDehum.PerformanceModel_Num) { // Performance Model Part A
2109 56002 : case PerformanceModel::Default: {
2110 56002 : WC0 = 0.0148880824323806;
2111 56002 : WC1 = -0.000283393198398211;
2112 56002 : WC2 = -0.87802168940547;
2113 56002 : WC3 = -0.000713615831236411;
2114 56002 : WC4 = 0.0311261188874622;
2115 56002 : WC5 = 1.51738892142485e-06;
2116 56002 : WC6 = 0.0287250198281021;
2117 56002 : WC7 = 4.94796903231558e-06;
2118 56002 : WC8 = 24.0771139652826;
2119 56002 : WC9 = 0.000122270283927978;
2120 56002 : WC10 = -0.0151657189566474;
2121 56002 : WC11 = 3.91641393230322e-08;
2122 56002 : WC12 = 0.126032651553348;
2123 56002 : WC13 = 0.000391653854431574;
2124 56002 : WC14 = 0.002160537360507;
2125 56002 : WC15 = 0.00132732844211593;
2126 :
2127 56002 : MinProcAirOutHumRat = WC0 + WC1 * ProcAirInTemp + WC2 * ProcAirInHumRat + WC3 * ProcAirVel + WC4 * ProcAirInTemp * ProcAirInHumRat +
2128 56002 : WC5 * ProcAirInTemp * ProcAirVel + WC6 * ProcAirInHumRat * ProcAirVel + WC7 * ProcAirInTemp * ProcAirInTemp +
2129 56002 : WC8 * ProcAirInHumRat * ProcAirInHumRat + WC9 * ProcAirVel * ProcAirVel +
2130 56002 : WC10 * ProcAirInTemp * ProcAirInTemp * ProcAirInHumRat * ProcAirInHumRat +
2131 56002 : WC11 * ProcAirInTemp * ProcAirInTemp * ProcAirVel * ProcAirVel +
2132 56002 : WC12 * ProcAirInHumRat * ProcAirInHumRat * ProcAirVel * ProcAirVel + WC13 * std::log(ProcAirInTemp) +
2133 56002 : WC14 * std::log(ProcAirInHumRat) + WC15 * std::log(ProcAirVel);
2134 :
2135 : // limit to 6 grains/lb (0.000857 kg/kg)
2136 :
2137 56002 : } break;
2138 0 : case PerformanceModel::UserCurves: {
2139 0 : MinProcAirOutHumRat = Curve::CurveValue(state, desicDehum.ProcHumRatCurvefTW, ProcAirInTemp, ProcAirInHumRat) *
2140 0 : Curve::CurveValue(state, desicDehum.ProcHumRatCurvefV, ProcAirVel);
2141 0 : } break;
2142 :
2143 0 : default: {
2144 :
2145 0 : ShowFatalError(state, format("Invalid performance model in desiccant dehumidifier = {}", desicDehum.PerformanceModel_Num));
2146 0 : } break;
2147 : } // Performance Model Part A
2148 :
2149 56002 : MinProcAirOutHumRat = max(MinProcAirOutHumRat, 0.000857);
2150 : }
2151 :
2152 92320 : if (MinProcAirOutHumRat >= ProcAirInHumRat) {
2153 0 : UnitOn = false;
2154 : }
2155 :
2156 92320 : if (UnitOn) {
2157 :
2158 : // Calculate partload fraction of dehumidification capacity required to meet setpoint
2159 56002 : PartLoad = 1.0;
2160 56002 : if (MinProcAirOutHumRat < HumRatNeeded) {
2161 37938 : PartLoad = (ProcAirInHumRat - HumRatNeeded) / (ProcAirInHumRat - MinProcAirOutHumRat);
2162 : }
2163 56002 : PartLoad = max(0.0, PartLoad);
2164 56002 : PartLoad = min(1.0, PartLoad);
2165 :
2166 56002 : switch (desicDehum.PerformanceModel_Num) { // Performance Model Part B
2167 56002 : case PerformanceModel::Default: {
2168 : // Calculate leaving conditions
2169 56002 : TC0 = -38.7782841989449;
2170 56002 : TC1 = 2.0127655837628;
2171 56002 : TC2 = 5212.49360216097;
2172 56002 : TC3 = 15.2362536782665;
2173 56002 : TC4 = -80.4910419759181;
2174 56002 : TC5 = -0.105014122001509;
2175 56002 : TC6 = -229.668673645144;
2176 56002 : TC7 = -0.015424703743461;
2177 56002 : TC8 = -69440.0689831847;
2178 56002 : TC9 = -1.6686064694322;
2179 56002 : TC10 = 38.5855718977592;
2180 56002 : TC11 = 0.000196395381206009;
2181 56002 : TC12 = 386.179386548324;
2182 56002 : TC13 = -0.801959614172614;
2183 56002 : TC14 = -3.33080986818745;
2184 56002 : TC15 = -15.2034386065714;
2185 :
2186 56002 : ProcAirOutTemp = TC0 + TC1 * ProcAirInTemp + TC2 * ProcAirInHumRat + TC3 * ProcAirVel + TC4 * ProcAirInTemp * ProcAirInHumRat +
2187 56002 : TC5 * ProcAirInTemp * ProcAirVel + TC6 * ProcAirInHumRat * ProcAirVel + TC7 * ProcAirInTemp * ProcAirInTemp +
2188 56002 : TC8 * ProcAirInHumRat * ProcAirInHumRat + TC9 * ProcAirVel * ProcAirVel +
2189 56002 : TC10 * ProcAirInTemp * ProcAirInTemp * ProcAirInHumRat * ProcAirInHumRat +
2190 56002 : TC11 * ProcAirInTemp * ProcAirInTemp * ProcAirVel * ProcAirVel +
2191 56002 : TC12 * ProcAirInHumRat * ProcAirInHumRat * ProcAirVel * ProcAirVel + TC13 * std::log(ProcAirInTemp) +
2192 56002 : TC14 * std::log(ProcAirInHumRat) + TC15 * std::log(ProcAirVel);
2193 :
2194 : // Regen energy
2195 56002 : QC0 = -27794046.6291107;
2196 56002 : QC1 = -235725.171759615;
2197 56002 : QC2 = 975461343.331328;
2198 56002 : QC3 = -686069.373946731;
2199 56002 : QC4 = -17717307.3766266;
2200 56002 : QC5 = 31482.2539662489;
2201 56002 : QC6 = 55296552.8260743;
2202 56002 : QC7 = 6195.36070023868;
2203 56002 : QC8 = -8304781359.40435;
2204 56002 : QC9 = -188987.543809419;
2205 56002 : QC10 = 3933449.40965846;
2206 56002 : QC11 = -6.66122876558634;
2207 56002 : QC12 = -349102295.417547;
2208 56002 : QC13 = 83672.179730172;
2209 56002 : QC14 = -6059524.33170538;
2210 56002 : QC15 = 1220523.39525162;
2211 :
2212 56002 : SpecRegenEnergy = QC0 + QC1 * ProcAirInTemp + QC2 * ProcAirInHumRat + QC3 * ProcAirVel + QC4 * ProcAirInTemp * ProcAirInHumRat +
2213 56002 : QC5 * ProcAirInTemp * ProcAirVel + QC6 * ProcAirInHumRat * ProcAirVel + QC7 * ProcAirInTemp * ProcAirInTemp +
2214 56002 : QC8 * ProcAirInHumRat * ProcAirInHumRat + QC9 * ProcAirVel * ProcAirVel +
2215 56002 : QC10 * ProcAirInTemp * ProcAirInTemp * ProcAirInHumRat * ProcAirInHumRat +
2216 56002 : QC11 * ProcAirInTemp * ProcAirInTemp * ProcAirVel * ProcAirVel +
2217 56002 : QC12 * ProcAirInHumRat * ProcAirInHumRat * ProcAirVel * ProcAirVel + QC13 * std::log(ProcAirInTemp) +
2218 56002 : QC14 * std::log(ProcAirInHumRat) + QC15 * std::log(ProcAirVel);
2219 :
2220 : // Regen face velocity
2221 56002 : RC0 = -4.67358908091488;
2222 56002 : RC1 = 0.0654323095468338;
2223 56002 : RC2 = 396.950518702316;
2224 56002 : RC3 = 1.52610165426736;
2225 56002 : RC4 = -11.3955868430328;
2226 56002 : RC5 = 0.00520693906104437;
2227 56002 : RC6 = 57.783645385621;
2228 56002 : RC7 = -0.000464800668311693;
2229 56002 : RC8 = -5958.78613212602;
2230 56002 : RC9 = -0.205375818291012;
2231 56002 : RC10 = 5.26762675442845;
2232 56002 : RC11 = -8.88452553055039e-05;
2233 56002 : RC12 = -182.382479369311;
2234 56002 : RC13 = -0.100289774002047;
2235 56002 : RC14 = -0.486980507964251;
2236 56002 : RC15 = -0.972715425435447;
2237 :
2238 56002 : RegenAirVel = RC0 + RC1 * ProcAirInTemp + RC2 * ProcAirInHumRat + RC3 * ProcAirVel + RC4 * ProcAirInTemp * ProcAirInHumRat +
2239 56002 : RC5 * ProcAirInTemp * ProcAirVel + RC6 * ProcAirInHumRat * ProcAirVel + RC7 * ProcAirInTemp * ProcAirInTemp +
2240 56002 : RC8 * ProcAirInHumRat * ProcAirInHumRat + RC9 * ProcAirVel * ProcAirVel +
2241 56002 : RC10 * ProcAirInTemp * ProcAirInTemp * ProcAirInHumRat * ProcAirInHumRat +
2242 56002 : RC11 * ProcAirInTemp * ProcAirInTemp * ProcAirVel * ProcAirVel +
2243 56002 : RC12 * ProcAirInHumRat * ProcAirInHumRat * ProcAirVel * ProcAirVel + RC13 * std::log(ProcAirInTemp) +
2244 56002 : RC14 * std::log(ProcAirInHumRat) + RC15 * std::log(ProcAirVel);
2245 :
2246 56002 : } break;
2247 0 : case PerformanceModel::UserCurves: {
2248 :
2249 0 : ProcAirOutTemp = Curve::CurveValue(state, desicDehum.ProcDryBulbCurvefTW, ProcAirInTemp, ProcAirInHumRat) *
2250 0 : Curve::CurveValue(state, desicDehum.ProcDryBulbCurvefV, ProcAirVel);
2251 :
2252 0 : SpecRegenEnergy = Curve::CurveValue(state, desicDehum.RegenEnergyCurvefTW, ProcAirInTemp, ProcAirInHumRat) *
2253 0 : Curve::CurveValue(state, desicDehum.RegenEnergyCurvefV, ProcAirVel);
2254 :
2255 0 : RegenAirVel = Curve::CurveValue(state, desicDehum.RegenVelCurvefTW, ProcAirInTemp, ProcAirInHumRat) *
2256 0 : Curve::CurveValue(state, desicDehum.RegenVelCurvefV, ProcAirVel);
2257 :
2258 0 : } break;
2259 0 : default: {
2260 :
2261 0 : ShowFatalError(state, format("Invalid performance model in desiccant dehumidifier = {}", desicDehum.PerformanceModel_Num));
2262 :
2263 : // Suppress uninitialized warnings
2264 0 : ProcAirOutTemp = 0.0;
2265 0 : SpecRegenEnergy = 0.0;
2266 0 : RegenAirVel = 0.0;
2267 0 : } break;
2268 : } // Performance Model Part B
2269 :
2270 56002 : ProcAirOutTemp = (1 - PartLoad) * ProcAirInTemp + (PartLoad)*ProcAirOutTemp;
2271 :
2272 56002 : ProcAirOutHumRat = (1 - PartLoad) * ProcAirInHumRat + (PartLoad)*MinProcAirOutHumRat;
2273 :
2274 : // Calculate water removal
2275 56002 : desicDehum.WaterRemoveRate = ProcAirMassFlowRate * (ProcAirInHumRat - ProcAirOutHumRat);
2276 :
2277 : // Adjust for regen inlet temperature
2278 56002 : SpecRegenEnergy *= (NomRegenTemp - RegenAirInTemp) / (NomRegenTemp - ProcAirInTemp);
2279 56002 : SpecRegenEnergy = max(SpecRegenEnergy, 0.0);
2280 56002 : QRegen = SpecRegenEnergy * desicDehum.WaterRemoveRate;
2281 :
2282 : // Above curves are based on a 90deg regen angle and 245deg process air angle
2283 56002 : RegenAirMassFlowRate = ProcAirMassFlowRate * 90.0 / 245.0 * RegenAirVel / ProcAirVel;
2284 :
2285 56002 : ElecUseRate = desicDehum.NomRotorPower;
2286 :
2287 : } else { // Unit is off
2288 :
2289 36318 : ProcAirOutTemp = ProcAirInTemp;
2290 36318 : ProcAirOutHumRat = ProcAirInHumRat;
2291 36318 : SpecRegenEnergy = 0.0;
2292 36318 : QRegen = 0.0;
2293 36318 : ElecUseRate = 0.0;
2294 36318 : RegenAirVel = 0.0;
2295 36318 : RegenAirMassFlowRate = 0.0;
2296 36318 : desicDehum.WaterRemoveRate = 0.0;
2297 36318 : PartLoad = 0.0;
2298 :
2299 : } // UnitOn/Off
2300 :
2301 : // Set regen mass flow
2302 92320 : state.dataLoopNodes->Node(desicDehum.RegenFanInNode).MassFlowRate = RegenAirMassFlowRate;
2303 92320 : state.dataLoopNodes->Node(desicDehum.RegenFanInNode).MassFlowRateMaxAvail = RegenAirMassFlowRate;
2304 : // Call regen fan
2305 92320 : state.dataFans->fans(desicDehum.RegenFanIndex)->simulate(state, FirstHVACIteration, _, _);
2306 :
2307 : // Call regen heating coil
2308 92320 : CalcNonDXHeatingCoils(state, DesicDehumNum, FirstHVACIteration, QRegen, QDelivered);
2309 :
2310 : // Verify is requestd flow was delivered (must do after heating coil has executed to pass flow to RegenAirInNode)
2311 92320 : if (state.dataLoopNodes->Node(desicDehum.RegenAirInNode).MassFlowRate != RegenAirMassFlowRate) {
2312 : // Initialize standard air density
2313 0 : ShowRecurringSevereErrorAtEnd(state,
2314 : "Improper flow delivered by desiccant regen fan - RESULTS INVALID! Check regen fan capacity and schedule.",
2315 0 : desicDehum.RegenFanErrorIndex1);
2316 0 : ShowRecurringContinueErrorAtEnd(state, desicDehum.DehumType + '=' + desicDehum.Name, desicDehum.RegenFanErrorIndex2);
2317 0 : ShowRecurringContinueErrorAtEnd(
2318 : state,
2319 0 : format("Flow requested [m3/s] from {} = {}", HVAC::fanTypeNames[(int)desicDehum.regenFanType], desicDehum.RegenFanName),
2320 0 : desicDehum.RegenFanErrorIndex3,
2321 0 : (RegenAirMassFlowRate / state.dataEnvrn->StdRhoAir));
2322 0 : ShowRecurringContinueErrorAtEnd(
2323 : state,
2324 : "Flow request varied from delivered by [m3/s]",
2325 0 : desicDehum.RegenFanErrorIndex4,
2326 0 : ((RegenAirMassFlowRate - state.dataLoopNodes->Node(desicDehum.RegenAirInNode).MassFlowRate) / state.dataEnvrn->StdRhoAir),
2327 0 : ((RegenAirMassFlowRate - state.dataLoopNodes->Node(desicDehum.RegenAirInNode).MassFlowRate) / state.dataEnvrn->StdRhoAir));
2328 : }
2329 :
2330 : // Verify is requestd heating was delivered
2331 92320 : if (QDelivered < QRegen) {
2332 0 : ShowRecurringSevereErrorAtEnd(
2333 : state,
2334 : "Inadequate heat delivered by desiccant regen coil - RESULTS INVALID! Check regen coil capacity and schedule.",
2335 0 : desicDehum.RegenCapErrorIndex1);
2336 0 : ShowRecurringContinueErrorAtEnd(state, desicDehum.DehumType + '=' + desicDehum.Name, desicDehum.RegenCapErrorIndex2);
2337 0 : ShowRecurringContinueErrorAtEnd(state,
2338 0 : format("Load requested [W] from {} = {}", desicDehum.RegenCoilType, desicDehum.RegenCoilName),
2339 0 : desicDehum.RegenCapErrorIndex3,
2340 : QRegen);
2341 0 : ShowRecurringContinueErrorAtEnd(state, "Load request exceeded delivered by [W]", desicDehum.RegenCapErrorIndex4, (QRegen - QDelivered));
2342 : }
2343 :
2344 92320 : desicDehum.SpecRegenEnergy = SpecRegenEnergy;
2345 92320 : desicDehum.QRegen = QRegen;
2346 92320 : desicDehum.ElecUseRate = ElecUseRate;
2347 92320 : desicDehum.PartLoad = PartLoad;
2348 :
2349 92320 : desicDehum.ProcAirOutMassFlowRate = ProcAirMassFlowRate;
2350 92320 : desicDehum.ProcAirOutTemp = ProcAirOutTemp;
2351 92320 : desicDehum.ProcAirOutHumRat = ProcAirOutHumRat;
2352 92320 : desicDehum.ProcAirOutEnthalpy = Psychrometrics::PsyHFnTdbW(ProcAirOutTemp, ProcAirOutHumRat);
2353 92320 : desicDehum.RegenAirInMassFlowRate = RegenAirMassFlowRate;
2354 92320 : desicDehum.RegenAirVel = RegenAirVel;
2355 92320 : }
2356 :
2357 191658 : void CalcGenericDesiccantDehumidifier(EnergyPlusData &state,
2358 : int const DesicDehumNum, // number of the current dehumidifier being simulated
2359 : Real64 const HumRatNeeded, // process air leaving humidity ratio set by controller [kg water/kg air]
2360 : bool const FirstHVACIteration // TRUE if 1st HVAC simulation of system timestep
2361 : )
2362 : {
2363 :
2364 : // SUBROUTINE INFORMATION:
2365 : // AUTHOR Mangesh Basarkar, FSEC
2366 : // DATE WRITTEN May 2007
2367 :
2368 : // PURPOSE OF THIS SUBROUTINE:
2369 : // Calculate the electricity consumption, regen heat requirements and the outlet
2370 : // conditions for a desiccant dehumidifier, given the inlet conditions,
2371 : // DX coil part-load ratio, and/or the needed process leaving humidity ratio.
2372 :
2373 : // METHODOLOGY EMPLOYED:
2374 : // Given the entering conditions, the full-load outlet conditions are calculated.
2375 : // Adjust for part-load if required.
2376 : // Calculate the required regen energy and call the regen coil and the regen fan.
2377 :
2378 : // REFERENCES:
2379 : // Kosar, D. 2006. Dehumidification Enhancements, ASHRAE Journal, Vol. 48, No. 2, February 2006.
2380 : // Kosar, D. et al. 2006. Dehumidification Enhancement of Direct Expansion Systems Through Component
2381 : // Augmentation of the Cooling Coil. 15th Symposium on Improving Building Systems in Hot and Humid
2382 : // Climates, July 24-26, 2006.
2383 :
2384 : // SUBROUTINE PARAMETER DEFINITIONS:
2385 191658 : Real64 constexpr MinVolFlowPerRatedTotQ(0.00002684); // m3/s per W = 200 cfm/ton,
2386 : // min vol flow per rated evaporator capacity
2387 :
2388 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
2389 : Real64 DDPartLoadRatio; // fraction of dehumidification capacity required to meet setpoint
2390 : Real64 MassFlowRateNew; // new required mass flow rate calculated to keep regen setpoint temperature (kg/s)
2391 : Real64 CondenserWasteHeat; // Condenser waste heat (W)
2392 : Real64 CpAir; // Specific heat of air (J/kg-K)
2393 : Real64 NewRegenInTemp; // new temp calculated from condenser waste heat (C)
2394 : Real64 ExhaustFanMassFlowRate; // exhaust fan mass flow rate (kg/s)
2395 : Real64 ExhaustFanPLR; // exhaust fan run time fraction calculated from new mass flow rate for regen side
2396 : Real64 ExhaustFanPowerMod; // used to calculate exhaust fan power from flow fraction
2397 : Real64 VolFlowPerRatedTotQ; // flow rate per rated total cooling capacity of the companion coil (m3/s/W)
2398 : Real64 FanDeltaT; // used to account for fan heat when calculating regeneration heater energy (C)
2399 : Real64 OnOffFanPLF; // save air loop fan part load fracton while calculating exhaust fan power
2400 : Real64 RegenSetPointTemp; // regeneration temperature setpoint (C)
2401 : int RegenCoilIndex; // index to regeneration heating coil, 0 when not used
2402 : int CompanionCoilIndexNum; // index for companion DX cooling coil, 0 when DX coil is not used
2403 : bool UnitOn; // unit on flag
2404 : // LOGICAL :: SimFlag ! used to turn off additional simulation if DX Coil is off
2405 : Real64 QRegen_OASysFanAdjust; // temporary variable used to adjust regen heater load during iteration
2406 :
2407 191658 : auto &desicDehum = state.dataDesiccantDehumidifiers->DesicDehum(DesicDehumNum);
2408 191658 : auto &QRegen(state.dataDesiccantDehumidifiers->QRegen);
2409 :
2410 191658 : UnitOn = false;
2411 191658 : DDPartLoadRatio = 0.0;
2412 191658 : RegenCoilIndex = desicDehum.RegenCoilIndex;
2413 191658 : FanDeltaT = 0.0;
2414 191658 : RegenSetPointTemp = desicDehum.RegenSetPointTemp;
2415 191658 : ExhaustFanMassFlowRate = 0.0;
2416 :
2417 : // Save OnOffFanPartLoadFraction while performing exhaust fan calculations
2418 191658 : OnOffFanPLF = state.dataHVACGlobal->OnOffFanPartLoadFraction;
2419 191658 : state.dataHVACGlobal->OnOffFanPartLoadFraction = 1.0;
2420 :
2421 191658 : if (desicDehum.CoilUpstreamOfProcessSide == Selection::Yes) {
2422 : // Cooling coil directly upstream of desiccant dehumidifier, dehumidifier runs in tandem with DX coil
2423 :
2424 15495 : CompanionCoilIndexNum = desicDehum.DXCoilIndex;
2425 : } else {
2426 : // desiccant dehumidifier determines its own PLR
2427 176163 : CompanionCoilIndexNum = 0;
2428 : }
2429 :
2430 191658 : if (HumRatNeeded < state.dataLoopNodes->Node(desicDehum.ProcAirInNode).HumRat) {
2431 4203 : UnitOn = true;
2432 : }
2433 :
2434 191658 : if (desicDehum.CoilUpstreamOfProcessSide == Selection::Yes) {
2435 15495 : if ((desicDehum.coolingCoil_TypeNum == HVAC::CoilDX_CoolingSingleSpeed) ||
2436 6632 : (desicDehum.coolingCoil_TypeNum == HVAC::CoilDX_CoolingTwoStageWHumControl)) {
2437 8863 : if (state.dataDXCoils->DXCoilPartLoadRatio(desicDehum.DXCoilIndex) == 0.0) {
2438 3052 : UnitOn = false;
2439 : }
2440 : }
2441 : }
2442 :
2443 191658 : if (UnitOn) {
2444 :
2445 3268 : if (desicDehum.RegenInletIsOutsideAirNode) {
2446 1846 : if (desicDehum.HXTypeNum == BalancedHX) {
2447 1846 : state.dataLoopNodes->Node(desicDehum.RegenAirInNode).MassFlowRate =
2448 1846 : state.dataLoopNodes->Node(desicDehum.ProcAirInNode).MassFlowRate;
2449 1846 : state.dataLoopNodes->Node(desicDehum.RegenAirInNode).MassFlowRateMaxAvail =
2450 1846 : state.dataLoopNodes->Node(desicDehum.ProcAirInNode).MassFlowRate;
2451 : }
2452 : }
2453 :
2454 : // Get conditions from DX Coil condenser if present (DXCoilIndex verified > 0 in GetInput)
2455 3268 : if (desicDehum.Preheat == Selection::Yes) {
2456 :
2457 : // condenser waste heat is proportional to DX coil PLR
2458 1846 : if ((desicDehum.coolingCoil_TypeNum == HVAC::CoilDX_CoolingSingleSpeed) ||
2459 477 : (desicDehum.coolingCoil_TypeNum == HVAC::CoilDX_CoolingTwoStageWHumControl)) {
2460 1369 : CondenserWasteHeat = state.dataHeatBal->HeatReclaimDXCoil(desicDehum.DXCoilIndex).AvailCapacity;
2461 1369 : state.dataHeatBal->HeatReclaimDXCoil(desicDehum.DXCoilIndex).AvailCapacity = 0.0;
2462 477 : } else if (desicDehum.coolingCoil_TypeNum == HVAC::Coil_CoolingAirToAirVariableSpeed) {
2463 477 : CondenserWasteHeat = state.dataHeatBal->HeatReclaimVS_Coil(desicDehum.DXCoilIndex).AvailCapacity;
2464 477 : state.dataHeatBal->HeatReclaimVS_Coil(desicDehum.DXCoilIndex).AvailCapacity = 0.0;
2465 : }
2466 :
2467 1846 : CpAir = Psychrometrics::PsyCpAirFnW(state.dataLoopNodes->Node(desicDehum.CondenserInletNode).HumRat);
2468 :
2469 1846 : if (desicDehum.regenFanPlace == HVAC::FanPlace::BlowThru) {
2470 0 : state.dataFans->fans(desicDehum.RegenFanIndex)->simulate(state, FirstHVACIteration, _, _);
2471 0 : FanDeltaT =
2472 0 : state.dataLoopNodes->Node(desicDehum.RegenFanOutNode).Temp - state.dataLoopNodes->Node(desicDehum.RegenFanInNode).Temp;
2473 : // Adjust setpoint to account for fan heat
2474 0 : RegenSetPointTemp -= FanDeltaT;
2475 : }
2476 :
2477 : // CompanionCoilIndexNum .GT. 0 means the same thing as desicDehum%CoilUpstreamOfProcessSide == Yes
2478 1846 : if (CompanionCoilIndexNum > 0) {
2479 :
2480 : // calculate PLR and actual condenser outlet node (regen inlet node) temperature
2481 1846 : if ((desicDehum.coolingCoil_TypeNum == HVAC::CoilDX_CoolingSingleSpeed) ||
2482 477 : (desicDehum.coolingCoil_TypeNum == HVAC::CoilDX_CoolingTwoStageWHumControl)) {
2483 1369 : DDPartLoadRatio = state.dataDXCoils->DXCoilPartLoadRatio(desicDehum.DXCoilIndex);
2484 2738 : if (state.dataDXCoils->DXCoilFanOp(desicDehum.DXCoilIndex) == HVAC::FanOp::Continuous) {
2485 1369 : NewRegenInTemp =
2486 1369 : state.dataLoopNodes->Node(desicDehum.CondenserInletNode).Temp +
2487 1369 : CondenserWasteHeat / (CpAir * (state.dataLoopNodes->Node(desicDehum.RegenAirInNode).MassFlowRate) * DDPartLoadRatio);
2488 1369 : CondenserWasteHeat /= DDPartLoadRatio;
2489 : } else {
2490 0 : NewRegenInTemp = state.dataLoopNodes->Node(desicDehum.CondenserInletNode).Temp +
2491 0 : CondenserWasteHeat / (CpAir * (state.dataLoopNodes->Node(desicDehum.RegenAirInNode).MassFlowRate));
2492 : }
2493 477 : } else if (desicDehum.coolingCoil_TypeNum == HVAC::Coil_CoolingAirToAirVariableSpeed) {
2494 477 : DDPartLoadRatio = 1.0; // condenser waste heat already includes modulation down
2495 477 : NewRegenInTemp = state.dataLoopNodes->Node(desicDehum.CondenserInletNode).Temp +
2496 477 : CondenserWasteHeat / (CpAir * (state.dataLoopNodes->Node(desicDehum.RegenAirInNode).MassFlowRate));
2497 : } else {
2498 0 : NewRegenInTemp = state.dataLoopNodes->Node(desicDehum.CondenserInletNode).Temp +
2499 0 : CondenserWasteHeat / (CpAir * (state.dataLoopNodes->Node(desicDehum.RegenAirInNode).MassFlowRate));
2500 : }
2501 : } else {
2502 0 : NewRegenInTemp = state.dataLoopNodes->Node(desicDehum.CondenserInletNode).Temp +
2503 0 : CondenserWasteHeat / (CpAir * (state.dataLoopNodes->Node(desicDehum.RegenAirInNode).MassFlowRate));
2504 : }
2505 :
2506 1846 : state.dataLoopNodes->Node(desicDehum.RegenAirInNode).Temp = NewRegenInTemp;
2507 1846 : state.dataLoopNodes->Node(desicDehum.RegenAirInNode).Enthalpy = Psychrometrics::PsyHFnTdbW(
2508 1846 : state.dataLoopNodes->Node(desicDehum.RegenAirInNode).Temp, state.dataLoopNodes->Node(desicDehum.RegenAirInNode).HumRat);
2509 1846 : MassFlowRateNew = 0.0;
2510 :
2511 1846 : if (desicDehum.ExhaustFanMaxVolFlowRate > 0) {
2512 :
2513 : // calculate mass flow rate required to maintain regen inlet setpoint temp
2514 1846 : if (NewRegenInTemp > RegenSetPointTemp) {
2515 1369 : if (RegenSetPointTemp - state.dataLoopNodes->Node(desicDehum.CondenserInletNode).Temp != 0.0) {
2516 1369 : MassFlowRateNew = max(0.0,
2517 : CondenserWasteHeat /
2518 1369 : (CpAir * (RegenSetPointTemp - state.dataLoopNodes->Node(desicDehum.CondenserInletNode).Temp)));
2519 : } else {
2520 0 : MassFlowRateNew = state.dataLoopNodes->Node(desicDehum.RegenAirInNode).MassFlowRate;
2521 : }
2522 : }
2523 :
2524 : // calculate exhaust fan mass flow rate and new regen inlet temperature (may not be at setpoint)
2525 1846 : if (MassFlowRateNew > state.dataLoopNodes->Node(desicDehum.RegenAirInNode).MassFlowRate) {
2526 1369 : ExhaustFanMassFlowRate = MassFlowRateNew - state.dataLoopNodes->Node(desicDehum.RegenAirInNode).MassFlowRate;
2527 1369 : ExhaustFanMassFlowRate = max(0.0, min(ExhaustFanMassFlowRate, desicDehum.ExhaustFanMaxMassFlowRate));
2528 :
2529 1369 : state.dataLoopNodes->Node(desicDehum.RegenAirInNode).Temp =
2530 1369 : state.dataLoopNodes->Node(desicDehum.CondenserInletNode).Temp +
2531 1369 : CondenserWasteHeat /
2532 1369 : (CpAir * (state.dataLoopNodes->Node(desicDehum.RegenAirInNode).MassFlowRate + ExhaustFanMassFlowRate));
2533 1369 : state.dataLoopNodes->Node(desicDehum.RegenAirInNode).HumRat = state.dataLoopNodes->Node(desicDehum.CondenserInletNode).HumRat;
2534 1369 : state.dataLoopNodes->Node(desicDehum.RegenAirInNode).Enthalpy = Psychrometrics::PsyHFnTdbW(
2535 1369 : state.dataLoopNodes->Node(desicDehum.RegenAirInNode).Temp, state.dataLoopNodes->Node(desicDehum.RegenAirInNode).HumRat);
2536 : }
2537 : }
2538 :
2539 1846 : if (RegenCoilIndex > 0) {
2540 1846 : if (NewRegenInTemp < RegenSetPointTemp) {
2541 477 : CpAir = Psychrometrics::PsyCpAirFnW(state.dataLoopNodes->Node(desicDehum.RegenAirInNode).HumRat);
2542 : }
2543 3692 : QRegen = max(0.0,
2544 1846 : (CpAir * state.dataLoopNodes->Node(desicDehum.RegenAirInNode).MassFlowRate *
2545 1846 : (RegenSetPointTemp - state.dataLoopNodes->Node(desicDehum.RegenAirInNode).Temp)));
2546 1846 : if (QRegen == 0.0) {
2547 1303 : QRegen = -1.0;
2548 : }
2549 : }
2550 :
2551 : // CompanionCoilIndexNum .EQ. 0 means the same thing as desicDehum%CoilUpstreamOfProcessSide == No
2552 1846 : if (CompanionCoilIndexNum == 0) {
2553 :
2554 0 : if (RegenCoilIndex > 0) {
2555 :
2556 0 : QRegen_OASysFanAdjust = QRegen;
2557 0 : if (desicDehum.regenFanPlace == HVAC::FanPlace::BlowThru) {
2558 0 : if (state.dataLoopNodes->Node(desicDehum.RegenAirInNode).MassFlowRate > 0.0) {
2559 : // For VAV systems, fan may restrict air flow during iteration. Adjust QRegen proportional to Mdot
2560 : // reduction through fan
2561 0 : QRegen_OASysFanAdjust *= state.dataLoopNodes->Node(desicDehum.RegenFanOutNode).MassFlowRate /
2562 0 : state.dataLoopNodes->Node(desicDehum.RegenFanInNode).MassFlowRate;
2563 : }
2564 : }
2565 :
2566 0 : CalcNonDXHeatingCoils(state, DesicDehumNum, FirstHVACIteration, QRegen_OASysFanAdjust);
2567 : }
2568 :
2569 0 : HeatRecovery::SimHeatRecovery(state,
2570 : desicDehum.HXName,
2571 : FirstHVACIteration,
2572 0 : desicDehum.CompIndex,
2573 : HVAC::FanOp::Continuous,
2574 0 : 1.0,
2575 0 : true,
2576 : CompanionCoilIndexNum,
2577 0 : desicDehum.RegenInletIsOutsideAirNode,
2578 : _,
2579 : _,
2580 0 : desicDehum.coolingCoil_TypeNum);
2581 :
2582 : // calculate desiccant part-load ratio
2583 0 : if (state.dataLoopNodes->Node(desicDehum.ProcAirInNode).HumRat != state.dataLoopNodes->Node(desicDehum.ProcAirOutNode).HumRat) {
2584 0 : DDPartLoadRatio = (state.dataLoopNodes->Node(desicDehum.ProcAirInNode).HumRat - HumRatNeeded) /
2585 0 : (state.dataLoopNodes->Node(desicDehum.ProcAirInNode).HumRat -
2586 0 : state.dataLoopNodes->Node(desicDehum.ProcAirOutNode).HumRat);
2587 0 : DDPartLoadRatio = max(0.0, min(1.0, DDPartLoadRatio));
2588 : } else {
2589 0 : DDPartLoadRatio = 1.0;
2590 : }
2591 : }
2592 :
2593 1846 : if (ExhaustFanMassFlowRate > 0.0) {
2594 :
2595 : // calculate exhaust fan mass flow rate due to desiccant system operation
2596 1369 : ExhaustFanMassFlowRate *= DDPartLoadRatio;
2597 :
2598 : // calculate exhaust fan PLR due to desiccant system operation
2599 1369 : ExhaustFanPLR = ExhaustFanMassFlowRate / desicDehum.ExhaustFanMaxMassFlowRate;
2600 :
2601 : // find exhaust fan power multiplier using exhaust fan part-load ratio
2602 1369 : if (desicDehum.ExhaustFanCurveIndex > 0) {
2603 1369 : ExhaustFanPowerMod = min(1.0, max(0.0, Curve::CurveValue(state, desicDehum.ExhaustFanCurveIndex, ExhaustFanPLR)));
2604 : } else {
2605 0 : ExhaustFanPowerMod = 1.0;
2606 : }
2607 :
2608 : // calculate exhaust fan power due to desiccant operation
2609 1369 : desicDehum.ExhaustFanPower = desicDehum.ExhaustFanMaxPower * ExhaustFanPowerMod;
2610 : }
2611 :
2612 : } else { // ELSE for IF(desicDehum%Preheat == Yes)THEN
2613 :
2614 1422 : if (state.dataLoopNodes->Node(desicDehum.ProcAirInNode).HumRat > HumRatNeeded) {
2615 :
2616 : // Get Full load output of desiccant wheel
2617 1422 : if (desicDehum.regenFanPlace == HVAC::FanPlace::BlowThru) {
2618 0 : state.dataFans->fans(desicDehum.RegenFanIndex)->simulate(state, FirstHVACIteration, _, _);
2619 :
2620 0 : FanDeltaT =
2621 0 : state.dataLoopNodes->Node(desicDehum.RegenFanOutNode).Temp - state.dataLoopNodes->Node(desicDehum.RegenFanInNode).Temp;
2622 0 : RegenSetPointTemp -= FanDeltaT;
2623 : }
2624 :
2625 1422 : if (RegenCoilIndex > 0) {
2626 1422 : CpAir = Psychrometrics::PsyCpAirFnW(state.dataLoopNodes->Node(desicDehum.RegenAirInNode).HumRat);
2627 2844 : QRegen = max(0.0,
2628 1422 : (CpAir * state.dataLoopNodes->Node(desicDehum.RegenAirInNode).MassFlowRate *
2629 1422 : (RegenSetPointTemp - state.dataLoopNodes->Node(desicDehum.RegenAirInNode).Temp)));
2630 :
2631 1422 : QRegen_OASysFanAdjust = QRegen;
2632 1422 : if (desicDehum.regenFanPlace == HVAC::FanPlace::BlowThru) {
2633 0 : if (state.dataLoopNodes->Node(desicDehum.RegenAirInNode).MassFlowRate > 0.0) {
2634 : // For VAV systems, fan may restrict air flow during iteration. Adjust QRegen proportional to Mdot
2635 : // reduction through fan
2636 0 : QRegen_OASysFanAdjust *= state.dataLoopNodes->Node(desicDehum.RegenFanOutNode).MassFlowRate /
2637 0 : state.dataLoopNodes->Node(desicDehum.RegenFanInNode).MassFlowRate;
2638 : }
2639 : }
2640 :
2641 1422 : if (QRegen_OASysFanAdjust == 0.0) {
2642 0 : QRegen_OASysFanAdjust = -1.0;
2643 : }
2644 1422 : CalcNonDXHeatingCoils(state, DesicDehumNum, FirstHVACIteration, QRegen_OASysFanAdjust);
2645 : }
2646 :
2647 : // CompanionCoilIndexNum .EQ. 0 means the same thing as desicDehum%CoilUpstreamOfProcessSide == No
2648 1422 : if (CompanionCoilIndexNum == 0) {
2649 5688 : HeatRecovery::SimHeatRecovery(state,
2650 : desicDehum.HXName,
2651 : FirstHVACIteration,
2652 1422 : desicDehum.CompIndex,
2653 : HVAC::FanOp::Continuous,
2654 2844 : 1.0,
2655 2844 : true,
2656 : CompanionCoilIndexNum,
2657 1422 : desicDehum.RegenInletIsOutsideAirNode,
2658 : _,
2659 : _,
2660 1422 : desicDehum.coolingCoil_TypeNum);
2661 :
2662 : // calculate desiccant part-load ratio
2663 1422 : if (state.dataLoopNodes->Node(desicDehum.ProcAirInNode).HumRat !=
2664 1422 : state.dataLoopNodes->Node(desicDehum.ProcAirOutNode).HumRat) {
2665 1422 : DDPartLoadRatio = (state.dataLoopNodes->Node(desicDehum.ProcAirInNode).HumRat - HumRatNeeded) /
2666 1422 : (state.dataLoopNodes->Node(desicDehum.ProcAirInNode).HumRat -
2667 1422 : state.dataLoopNodes->Node(desicDehum.ProcAirOutNode).HumRat);
2668 1422 : DDPartLoadRatio = max(0.0, min(1.0, DDPartLoadRatio));
2669 : } else {
2670 0 : DDPartLoadRatio = 1.0;
2671 : }
2672 : } else {
2673 0 : if ((desicDehum.coolingCoil_TypeNum == HVAC::CoilDX_CoolingSingleSpeed) ||
2674 0 : (desicDehum.coolingCoil_TypeNum == HVAC::CoilDX_CoolingTwoStageWHumControl)) {
2675 0 : DDPartLoadRatio = state.dataDXCoils->DXCoilPartLoadRatio(desicDehum.DXCoilIndex);
2676 0 : } else if (desicDehum.coolingCoil_TypeNum == HVAC::Coil_CoolingAirToAirVariableSpeed) {
2677 0 : DDPartLoadRatio = 1.0; // condenser waste heat already includes modulation down
2678 : }
2679 : }
2680 : } else { // ELSE for IF(state.dataLoopNodes->Node(desicDehum%ProcAirInNode)%HumRat .GT. HumRatNeeded)THEN
2681 0 : DDPartLoadRatio = 0.0;
2682 : } // END IF for IF(state.dataLoopNodes->Node(desicDehum%ProcAirInNode)%HumRat .GT. HumRatNeeded)THEN
2683 :
2684 : } // END IF for IF(desicDehum%Preheat == Yes)THEN
2685 :
2686 3268 : desicDehum.PartLoad = DDPartLoadRatio;
2687 3268 : QRegen_OASysFanAdjust = QRegen;
2688 :
2689 : // set average regeneration air mass flow rate based on desiccant cycling ratio (DDPartLoadRatio)
2690 3268 : if (desicDehum.RegenInletIsOutsideAirNode) {
2691 1846 : state.dataLoopNodes->Node(desicDehum.RegenAirInNode).MassFlowRate *= DDPartLoadRatio;
2692 :
2693 : // **RR moved to here, only adjust regen heater load if mass flow rate is changed
2694 : // adjust regen heating coil capacity based on desiccant cycling ratio (PLR)
2695 1846 : QRegen_OASysFanAdjust *= DDPartLoadRatio;
2696 : }
2697 :
2698 : // Call regen fan, balanced desiccant HX and heating coil
2699 3268 : if (desicDehum.regenFanPlace == HVAC::FanPlace::BlowThru) {
2700 0 : state.dataFans->fans(desicDehum.RegenFanIndex)->simulate(state, FirstHVACIteration, _, _);
2701 : }
2702 :
2703 3268 : if (RegenCoilIndex > 0) {
2704 :
2705 : //! adjust regen heating coil capacity based on desiccant cycling ratio (PLR)
2706 : // QRegen_OASysFanAdjust = QRegen * DDPartLoadRatio
2707 :
2708 3268 : if (desicDehum.regenFanPlace == HVAC::FanPlace::BlowThru) {
2709 0 : if (state.dataLoopNodes->Node(desicDehum.RegenAirInNode).MassFlowRate > 0.0) {
2710 : // For VAV systems, fan may restrict air flow during iteration. Adjust QRegen proportional to Mdot reduction through fan
2711 0 : QRegen_OASysFanAdjust *= state.dataLoopNodes->Node(desicDehum.RegenFanOutNode).MassFlowRate /
2712 0 : state.dataLoopNodes->Node(desicDehum.RegenFanInNode).MassFlowRate;
2713 : }
2714 : }
2715 :
2716 3268 : if (QRegen_OASysFanAdjust == 0.0) {
2717 0 : QRegen_OASysFanAdjust = -1.0;
2718 : }
2719 3268 : CalcNonDXHeatingCoils(state, DesicDehumNum, FirstHVACIteration, QRegen_OASysFanAdjust);
2720 : }
2721 :
2722 16340 : HeatRecovery::SimHeatRecovery(state,
2723 : desicDehum.HXName,
2724 : FirstHVACIteration,
2725 3268 : desicDehum.CompIndex,
2726 : HVAC::FanOp::Continuous,
2727 : DDPartLoadRatio,
2728 6536 : true,
2729 : CompanionCoilIndexNum,
2730 3268 : desicDehum.RegenInletIsOutsideAirNode,
2731 : _,
2732 : _,
2733 3268 : desicDehum.coolingCoil_TypeNum);
2734 :
2735 3268 : if (desicDehum.regenFanPlace == HVAC::FanPlace::DrawThru) {
2736 3268 : state.dataFans->fans(desicDehum.RegenFanIndex)->simulate(state, FirstHVACIteration, _, _);
2737 : }
2738 :
2739 : // Calculate water removal
2740 3268 : desicDehum.WaterRemoveRate =
2741 3268 : state.dataLoopNodes->Node(desicDehum.ProcAirInNode).MassFlowRate *
2742 3268 : (state.dataLoopNodes->Node(desicDehum.ProcAirInNode).HumRat - state.dataLoopNodes->Node(desicDehum.ProcAirOutNode).HumRat);
2743 :
2744 : // If preheat is Yes, exhaust fan is condenser fan, if CoilUpstreamOfProcessSide is No, DD runs an its own PLR
2745 3268 : if (desicDehum.Preheat == Selection::Yes && desicDehum.CoilUpstreamOfProcessSide == Selection::No) {
2746 : // should actually use DX coil RTF instead of PLR since fan power is being calculated
2747 0 : if ((desicDehum.coolingCoil_TypeNum == HVAC::CoilDX_CoolingSingleSpeed) ||
2748 0 : (desicDehum.coolingCoil_TypeNum == HVAC::CoilDX_CoolingTwoStageWHumControl)) {
2749 0 : desicDehum.ExhaustFanPower += max(
2750 0 : 0.0, (desicDehum.ExhaustFanMaxPower * (state.dataDXCoils->DXCoilPartLoadRatio(desicDehum.DXCoilIndex) - DDPartLoadRatio)));
2751 0 : } else if (desicDehum.coolingCoil_TypeNum == HVAC::Coil_CoolingAirToAirVariableSpeed) {
2752 0 : desicDehum.ExhaustFanPower += max(0.0, (desicDehum.ExhaustFanMaxPower * (1.0 - DDPartLoadRatio)));
2753 : }
2754 : }
2755 :
2756 : } else { // unit must be off
2757 :
2758 188390 : desicDehum.PartLoad = 0.0;
2759 :
2760 188390 : if (desicDehum.RegenInletIsOutsideAirNode) {
2761 13649 : state.dataLoopNodes->Node(desicDehum.RegenAirInNode).MassFlowRate = 0.0;
2762 13649 : state.dataLoopNodes->Node(desicDehum.RegenAirInNode).MassFlowRateMaxAvail = 0.0;
2763 : }
2764 :
2765 188390 : if (desicDehum.regenFanPlace == HVAC::FanPlace::BlowThru) {
2766 0 : state.dataFans->fans(desicDehum.RegenFanIndex)->simulate(state, FirstHVACIteration, _, _);
2767 : }
2768 :
2769 188390 : if (RegenCoilIndex > 0) {
2770 188390 : CalcNonDXHeatingCoils(state, DesicDehumNum, FirstHVACIteration, -1.0);
2771 : }
2772 :
2773 753560 : HeatRecovery::SimHeatRecovery(state,
2774 : desicDehum.HXName,
2775 : FirstHVACIteration,
2776 188390 : desicDehum.CompIndex,
2777 : HVAC::FanOp::Continuous,
2778 376780 : 0.0,
2779 376780 : false,
2780 : CompanionCoilIndexNum,
2781 188390 : desicDehum.RegenInletIsOutsideAirNode,
2782 : _,
2783 : _,
2784 188390 : desicDehum.coolingCoil_TypeNum);
2785 :
2786 188390 : if (desicDehum.regenFanPlace == HVAC::FanPlace::DrawThru) {
2787 188390 : state.dataFans->fans(desicDehum.RegenFanIndex)->simulate(state, FirstHVACIteration, _, _);
2788 : }
2789 :
2790 : // Turn on exhaust fan if DX Coil is operating
2791 188390 : if (desicDehum.ExhaustFanMaxVolFlowRate > 0) {
2792 13649 : if (desicDehum.DXCoilIndex > 0) {
2793 13649 : if ((desicDehum.coolingCoil_TypeNum == HVAC::CoilDX_CoolingSingleSpeed) ||
2794 6155 : (desicDehum.coolingCoil_TypeNum == HVAC::CoilDX_CoolingTwoStageWHumControl)) {
2795 7494 : DDPartLoadRatio = state.dataDXCoils->DXCoilPartLoadRatio(desicDehum.DXCoilIndex);
2796 6155 : } else if (desicDehum.coolingCoil_TypeNum == HVAC::Coil_CoolingAirToAirVariableSpeed) {
2797 6155 : DDPartLoadRatio = 1.0; // condenser waste heat already includes modulation down
2798 : }
2799 13649 : desicDehum.ExhaustFanPower = desicDehum.ExhaustFanMaxPower * DDPartLoadRatio;
2800 13649 : ExhaustFanMassFlowRate = desicDehum.ExhaustFanMaxMassFlowRate * DDPartLoadRatio;
2801 : }
2802 : }
2803 :
2804 : } // UnitOn/Off
2805 :
2806 : // check condenser minimum flow per rated total capacity
2807 191658 : if (DDPartLoadRatio > 0.0 && desicDehum.ExhaustFanMaxVolFlowRate > 0.0) {
2808 12443 : VolFlowPerRatedTotQ = (state.dataLoopNodes->Node(desicDehum.RegenAirInNode).MassFlowRate + ExhaustFanMassFlowRate) /
2809 12443 : max(0.00001, (desicDehum.CompanionCoilCapacity * DDPartLoadRatio * state.dataEnvrn->StdRhoAir));
2810 12443 : if (!state.dataGlobal->WarmupFlag && (VolFlowPerRatedTotQ < MinVolFlowPerRatedTotQ)) {
2811 0 : ++desicDehum.ErrCount;
2812 0 : if (desicDehum.ErrCount < 2) {
2813 0 : ShowWarningError(state,
2814 0 : format("{} \"{}\" - Air volume flow rate per watt of total condenser waste heat is below the minimum "
2815 : "recommended at {:N} m3/s/W.",
2816 0 : desicDehum.DehumType,
2817 0 : desicDehum.Name,
2818 : VolFlowPerRatedTotQ));
2819 0 : ShowContinueErrorTimeStamp(state, "");
2820 0 : ShowContinueError(state,
2821 0 : format("Expected minimum for VolumeFlowperRatedTotalCondenserWasteHeat = [{:N}]", MinVolFlowPerRatedTotQ));
2822 0 : ShowContinueError(state, "Possible causes include inconsistent air flow rates in system components ");
2823 0 : ShowContinueError(state, "on the regeneration side of the desiccant dehumidifier.");
2824 : } else {
2825 0 : ShowRecurringWarningErrorAtEnd(
2826 : state,
2827 0 : desicDehum.DehumType + " \"" + desicDehum.Name +
2828 : "\" - Air volume flow rate per watt of rated total cooling capacity is out of range error continues...",
2829 0 : desicDehum.ErrIndex1,
2830 : VolFlowPerRatedTotQ,
2831 : VolFlowPerRatedTotQ);
2832 : }
2833 : } // flow per rated total capacity check ends
2834 : }
2835 :
2836 : // Reset OnOffFanPartLoadFraction for process side fan calculations
2837 191658 : state.dataHVACGlobal->OnOffFanPartLoadFraction = OnOffFanPLF;
2838 191658 : }
2839 :
2840 283978 : void UpdateDesiccantDehumidifier(EnergyPlusData &state, int const DesicDehumNum) // number of the current dehumidifier being simulated
2841 : {
2842 :
2843 : // SUBROUTINE INFORMATION:
2844 : // AUTHOR Michael J. Witte, GARD Analytics, Inc.
2845 : // for Gas Research Institute
2846 : // DATE WRITTEN March 2001
2847 :
2848 : // PURPOSE OF THIS SUBROUTINE:
2849 : // Moves dehumidifier output to the outlet nodes.
2850 :
2851 283978 : switch (state.dataDesiccantDehumidifiers->DesicDehum(DesicDehumNum).DehumTypeCode) {
2852 92320 : case DesicDehumType::Solid: {
2853 92320 : int ProcInNode = state.dataDesiccantDehumidifiers->DesicDehum(DesicDehumNum).ProcAirInNode;
2854 92320 : int ProcOutNode = state.dataDesiccantDehumidifiers->DesicDehum(DesicDehumNum).ProcAirOutNode;
2855 : // Set the process outlet air node of the dehumidifier
2856 92320 : state.dataLoopNodes->Node(ProcOutNode).Temp = state.dataDesiccantDehumidifiers->DesicDehum(DesicDehumNum).ProcAirOutTemp;
2857 92320 : state.dataLoopNodes->Node(ProcOutNode).HumRat = state.dataDesiccantDehumidifiers->DesicDehum(DesicDehumNum).ProcAirOutHumRat;
2858 92320 : state.dataLoopNodes->Node(ProcOutNode).Enthalpy = state.dataDesiccantDehumidifiers->DesicDehum(DesicDehumNum).ProcAirOutEnthalpy;
2859 :
2860 : // Set the process outlet nodes for properties that just pass through & not used
2861 92320 : state.dataLoopNodes->Node(ProcOutNode).Quality = state.dataLoopNodes->Node(ProcInNode).Quality;
2862 92320 : state.dataLoopNodes->Node(ProcOutNode).Press = state.dataLoopNodes->Node(ProcInNode).Press;
2863 92320 : state.dataLoopNodes->Node(ProcOutNode).MassFlowRate = state.dataLoopNodes->Node(ProcInNode).MassFlowRate;
2864 92320 : state.dataLoopNodes->Node(ProcOutNode).MassFlowRateMin = state.dataLoopNodes->Node(ProcInNode).MassFlowRateMin;
2865 92320 : state.dataLoopNodes->Node(ProcOutNode).MassFlowRateMax = state.dataLoopNodes->Node(ProcInNode).MassFlowRateMax;
2866 92320 : state.dataLoopNodes->Node(ProcOutNode).MassFlowRateMinAvail = state.dataLoopNodes->Node(ProcInNode).MassFlowRateMinAvail;
2867 92320 : state.dataLoopNodes->Node(ProcOutNode).MassFlowRateMaxAvail = state.dataLoopNodes->Node(ProcInNode).MassFlowRateMaxAvail;
2868 :
2869 : // RegenInNode =DesicDehum(DesicDehumNum)%RegenAirInNode
2870 : // RegenOutNode = DesicDehum(DesicDehumNum)%RegenAirOutNode
2871 : // Set the regen outlet air node of the dehumidifier
2872 : // Node(RegenOutNode)%Temp = DesicDehum(DesicDehumNum)%RegenAirOutTemp
2873 : // Node(RegenOutNode)%HumRat = DesicDehum(DesicDehumNum)%RegenAirOutHumRat
2874 : // Node(RegenOutNode)%Enthalpy = DesicDehum(DesicDehumNum)%RegenAirOutEnthalpy
2875 :
2876 : // Set the regen outlet nodes for properties that just pass through & not used
2877 : // Node(RegenOutNode)%Quality = Node(RegenInNode)%Quality
2878 : // Node(RegenOutNode)%Press = Node(RegenInNode)%Press
2879 : // Node(RegenOutNode)%MassFlowRate = Node(RegenInNode)%MassFlowRate
2880 : // Node(RegenOutNode)%MassFlowRateMin = Node(RegenInNode)%MassFlowRateMin
2881 : // Node(RegenOutNode)%MassFlowRateMax = Node(RegenInNode)%MassFlowRateMax
2882 : // Node(RegenOutNode)%MassFlowRateMinAvail= Node(RegenInNode)%MassFlowRateMinAvail
2883 : // Node(RegenOutNode)%MassFlowRateMaxAvail= Node(RegenInNode)%MassFlowRateMaxAvail
2884 :
2885 92320 : } break;
2886 191658 : case DesicDehumType::Generic: {
2887 191658 : return;
2888 : } break;
2889 0 : default:
2890 0 : break;
2891 : }
2892 : }
2893 :
2894 283978 : void ReportDesiccantDehumidifier(EnergyPlusData &state, int const DesicDehumNum) // number of the current dehumidifier being simulated
2895 : {
2896 :
2897 : // SUBROUTINE INFORMATION:
2898 : // AUTHOR Michael J. Witte, GARD Analytics, Inc.
2899 : // for Gas Research Institute
2900 : // DATE WRITTEN March 2001
2901 : // MODIFIED June 2007, R. Raustad, Added new dehumidifier type -- DESICCANT DEHUMIDIFIER
2902 :
2903 : // PURPOSE OF THIS SUBROUTINE:
2904 : // Fill remaining report variables
2905 :
2906 283978 : Real64 TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
2907 :
2908 283978 : switch (state.dataDesiccantDehumidifiers->DesicDehum(DesicDehumNum).DehumTypeCode) {
2909 92320 : case DesicDehumType::Solid: {
2910 92320 : state.dataDesiccantDehumidifiers->DesicDehum(DesicDehumNum).WaterRemove =
2911 92320 : state.dataDesiccantDehumidifiers->DesicDehum(DesicDehumNum).WaterRemoveRate * TimeStepSysSec;
2912 92320 : state.dataDesiccantDehumidifiers->DesicDehum(DesicDehumNum).RegenEnergy =
2913 92320 : state.dataDesiccantDehumidifiers->DesicDehum(DesicDehumNum).QRegen * TimeStepSysSec;
2914 92320 : state.dataDesiccantDehumidifiers->DesicDehum(DesicDehumNum).ElecUseEnergy =
2915 92320 : state.dataDesiccantDehumidifiers->DesicDehum(DesicDehumNum).ElecUseRate * TimeStepSysSec;
2916 92320 : } break;
2917 191658 : case DesicDehumType::Generic: {
2918 191658 : state.dataDesiccantDehumidifiers->DesicDehum(DesicDehumNum).WaterRemove =
2919 191658 : state.dataDesiccantDehumidifiers->DesicDehum(DesicDehumNum).WaterRemoveRate * TimeStepSysSec;
2920 191658 : state.dataDesiccantDehumidifiers->DesicDehum(DesicDehumNum).ExhaustFanElecConsumption =
2921 191658 : state.dataDesiccantDehumidifiers->DesicDehum(DesicDehumNum).ExhaustFanPower * TimeStepSysSec;
2922 191658 : } break;
2923 0 : default:
2924 0 : break;
2925 : }
2926 283978 : }
2927 :
2928 377720 : void CalcNonDXHeatingCoils(EnergyPlusData &state,
2929 : int const DesicDehumNum, // Desiccant dehumidifier unit index
2930 : bool const FirstHVACIteration, // flag for first HVAC iteration in the time step
2931 : Real64 const RegenCoilLoad, // heating coil load to be met (Watts)
2932 : ObjexxFCL::Optional<Real64> RegenCoilLoadmet // heating load met
2933 : )
2934 : {
2935 :
2936 : // SUBROUTINE INFORMATION:
2937 : // AUTHOR Bereket Nigusse, FSEC/UCF
2938 : // DATE WRITTEN January 2012
2939 :
2940 : // PURPOSE OF THIS SUBROUTINE:
2941 : // This subroutine simulates the four non dx heating coil types: Gas, Electric, hot water and steam.
2942 :
2943 : // METHODOLOGY EMPLOYED:
2944 : // Simply calls the different heating coil component. The hot water flow rate matching the coil load
2945 : // is calculated iteratively.
2946 :
2947 : // SUBROUTINE PARAMETER DEFINITIONS:
2948 377720 : Real64 constexpr ErrTolerance(0.001); // convergence limit for hotwater coil
2949 377720 : int constexpr SolveMaxIter(50); // Max iteration for SolveRoot
2950 :
2951 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
2952 : Real64 RegenCoilActual; // actual heating load met
2953 : Real64 mdot; // heating coil steam or hot water mass flow rate
2954 : Real64 MinWaterFlow; // minimum hot water mass flow rate
2955 : // unused REAL(r64) :: PartLoadFraction ! heating or cooling part load fraction
2956 : Real64 MaxHotWaterFlow; // maximum hot water mass flow rate, kg/s
2957 : Real64 HotWaterMdot; // actual hot water mass flow rate
2958 :
2959 377720 : auto &desicDehum = state.dataDesiccantDehumidifiers->DesicDehum(DesicDehumNum);
2960 :
2961 377720 : RegenCoilActual = 0.0;
2962 377720 : if (RegenCoilLoad > HVAC::SmallLoad) {
2963 59323 : switch (desicDehum.RegenCoilType_Num) {
2964 59323 : case HVAC::Coil_HeatingGasOrOtherFuel:
2965 : case HVAC::Coil_HeatingElectric: {
2966 118646 : HeatingCoils::SimulateHeatingCoilComponents(
2967 59323 : state, desicDehum.RegenCoilName, FirstHVACIteration, RegenCoilLoad, desicDehum.RegenCoilIndex, RegenCoilActual);
2968 59323 : } break;
2969 0 : case HVAC::Coil_HeatingWater: {
2970 0 : MaxHotWaterFlow = desicDehum.MaxCoilFluidFlow;
2971 0 : PlantUtilities::SetComponentFlowRate(
2972 0 : state, MaxHotWaterFlow, desicDehum.CoilControlNode, desicDehum.CoilOutletNode, desicDehum.plantLoc);
2973 0 : RegenCoilActual = RegenCoilLoad;
2974 : // simulate the regenerator hot water heating coil
2975 0 : WaterCoils::SimulateWaterCoilComponents(
2976 0 : state, desicDehum.RegenCoilName, FirstHVACIteration, desicDehum.RegenCoilIndex, RegenCoilActual);
2977 :
2978 0 : if (RegenCoilActual > (RegenCoilLoad + HVAC::SmallLoad)) {
2979 : // control water flow to obtain output matching RegenCoilLoad
2980 0 : int SolFlag = 0;
2981 0 : MinWaterFlow = 0.0;
2982 0 : auto f = [&state, DesicDehumNum, FirstHVACIteration, RegenCoilLoad](Real64 HWFlow) {
2983 0 : Real64 RegenCoilHeatLoad = RegenCoilLoad;
2984 0 : Real64 RegenCoilActual = RegenCoilHeatLoad;
2985 0 : Real64 mdot = HWFlow;
2986 0 : PlantUtilities::SetComponentFlowRate(state,
2987 : mdot,
2988 0 : state.dataDesiccantDehumidifiers->DesicDehum(DesicDehumNum).CoilControlNode,
2989 0 : state.dataDesiccantDehumidifiers->DesicDehum(DesicDehumNum).CoilOutletNode,
2990 0 : state.dataDesiccantDehumidifiers->DesicDehum(DesicDehumNum).plantLoc);
2991 :
2992 : // simulate the hot water regenerator heating coil
2993 0 : WaterCoils::SimulateWaterCoilComponents(state,
2994 0 : state.dataDesiccantDehumidifiers->DesicDehum(DesicDehumNum).RegenCoilName,
2995 : FirstHVACIteration,
2996 0 : state.dataDesiccantDehumidifiers->DesicDehum(DesicDehumNum).RegenCoilIndex,
2997 : RegenCoilActual);
2998 0 : if (RegenCoilHeatLoad != 0.0) {
2999 0 : return (RegenCoilActual - RegenCoilHeatLoad) / RegenCoilHeatLoad;
3000 : } else { // Autodesk:Return ELSE added to assure return value is set
3001 0 : return 0.0;
3002 : }
3003 0 : };
3004 0 : General::SolveRoot(state, ErrTolerance, SolveMaxIter, SolFlag, HotWaterMdot, f, MinWaterFlow, MaxHotWaterFlow);
3005 0 : if (SolFlag == -1) {
3006 0 : if (desicDehum.HotWaterCoilMaxIterIndex == 0) {
3007 0 : ShowWarningMessage(
3008 : state,
3009 0 : format("CalcNonDXHeatingCoils: Hot water coil control failed for {}=\"{}\"", desicDehum.DehumType, desicDehum.Name));
3010 0 : ShowContinueErrorTimeStamp(state, "");
3011 0 : ShowContinueError(state,
3012 0 : format("...Iteration limit [{}] exceeded in calculating hot water mass flow rate", SolveMaxIter));
3013 : }
3014 0 : ShowRecurringWarningErrorAtEnd(
3015 : state,
3016 0 : format("CalcNonDXHeatingCoils: Hot water coil control failed (iteration limit [{}]) for {}=\"{}\"",
3017 : SolveMaxIter,
3018 0 : desicDehum.DehumType,
3019 0 : desicDehum.Name),
3020 0 : desicDehum.HotWaterCoilMaxIterIndex);
3021 0 : } else if (SolFlag == -2) {
3022 0 : if (desicDehum.HotWaterCoilMaxIterIndex2 == 0) {
3023 0 : ShowWarningMessage(state,
3024 0 : format("CalcNonDXHeatingCoils: Hot water coil control failed (maximum flow limits) for {}=\"{}\"",
3025 0 : desicDehum.DehumType,
3026 0 : desicDehum.Name));
3027 0 : ShowContinueErrorTimeStamp(state, "");
3028 0 : ShowContinueError(state, "...Bad hot water maximum flow rate limits");
3029 0 : ShowContinueError(state, format("...Given minimum water flow rate={:.3R} kg/s", MinWaterFlow));
3030 0 : ShowContinueError(state, format("...Given maximum water flow rate={:.3R} kg/s", MaxHotWaterFlow));
3031 : }
3032 0 : ShowRecurringWarningErrorAtEnd(state,
3033 0 : "CalcNonDXHeatingCoils: Hot water coil control failed (flow limits) for " +
3034 0 : desicDehum.DehumType + "=\"" + desicDehum.Name + "\"",
3035 0 : desicDehum.HotWaterCoilMaxIterIndex2,
3036 : MaxHotWaterFlow,
3037 : MinWaterFlow,
3038 : _,
3039 : "[kg/s]",
3040 : "[kg/s]");
3041 : }
3042 :
3043 0 : RegenCoilActual = RegenCoilLoad;
3044 : // simulate the regenerator hot water heating coil
3045 0 : WaterCoils::SimulateWaterCoilComponents(
3046 0 : state, desicDehum.RegenCoilName, FirstHVACIteration, desicDehum.RegenCoilIndex, RegenCoilActual);
3047 : }
3048 0 : } break;
3049 0 : case HVAC::Coil_HeatingSteam: {
3050 0 : mdot = desicDehum.MaxCoilFluidFlow;
3051 0 : PlantUtilities::SetComponentFlowRate(state, mdot, desicDehum.CoilControlNode, desicDehum.CoilOutletNode, desicDehum.plantLoc);
3052 : // simulate the regenerator steam heating coil
3053 0 : SteamCoils::SimulateSteamCoilComponents(
3054 0 : state, desicDehum.RegenCoilName, FirstHVACIteration, desicDehum.RegenCoilIndex, RegenCoilLoad, RegenCoilActual);
3055 0 : } break;
3056 0 : default:
3057 0 : break;
3058 : }
3059 : } else {
3060 318397 : switch (desicDehum.RegenCoilType_Num) {
3061 318397 : case HVAC::Coil_HeatingGasOrOtherFuel:
3062 : case HVAC::Coil_HeatingElectric: {
3063 636794 : HeatingCoils::SimulateHeatingCoilComponents(
3064 318397 : state, desicDehum.RegenCoilName, FirstHVACIteration, RegenCoilLoad, desicDehum.RegenCoilIndex, RegenCoilActual);
3065 318397 : } break;
3066 0 : case HVAC::Coil_HeatingWater: {
3067 0 : mdot = 0.0;
3068 0 : PlantUtilities::SetComponentFlowRate(state, mdot, desicDehum.CoilControlNode, desicDehum.CoilOutletNode, desicDehum.plantLoc);
3069 0 : RegenCoilActual = RegenCoilLoad;
3070 : // simulate the regenerator hot water heating coil
3071 0 : WaterCoils::SimulateWaterCoilComponents(
3072 0 : state, desicDehum.RegenCoilName, FirstHVACIteration, desicDehum.RegenCoilIndex, RegenCoilActual);
3073 0 : } break;
3074 0 : case HVAC::Coil_HeatingSteam: {
3075 0 : mdot = 0.0;
3076 0 : PlantUtilities::SetComponentFlowRate(state, mdot, desicDehum.CoilControlNode, desicDehum.CoilOutletNode, desicDehum.plantLoc);
3077 : // simulate the regenerator steam heating coil
3078 0 : SteamCoils::SimulateSteamCoilComponents(
3079 0 : state, desicDehum.RegenCoilName, FirstHVACIteration, desicDehum.RegenCoilIndex, RegenCoilLoad, RegenCoilActual);
3080 0 : } break;
3081 0 : default:
3082 0 : break;
3083 : }
3084 : }
3085 377720 : if (present(RegenCoilLoadmet)) {
3086 92320 : RegenCoilLoadmet = RegenCoilActual;
3087 : }
3088 377720 : }
3089 :
3090 0 : int GetProcAirInletNodeNum(EnergyPlusData &state, std::string const &DesicDehumName, bool &ErrorsFound)
3091 : {
3092 :
3093 : // FUNCTION INFORMATION:
3094 : // AUTHOR Lixing Gu
3095 : // DATE WRITTEN May 2019
3096 :
3097 : // PURPOSE OF THIS FUNCTION:
3098 : // This function looks up the given Desiccant Dehumidifier and returns the process air inlet node number.
3099 : // If incorrect Desiccant Dehumidifier name is given, ErrorsFound is returned as true and node number as zero.
3100 :
3101 : // Obtains and Allocates heat exchanger related parameters from input file
3102 0 : if (state.dataDesiccantDehumidifiers->GetInputDesiccantDehumidifier) {
3103 0 : GetDesiccantDehumidifierInput(state);
3104 0 : state.dataDesiccantDehumidifiers->GetInputDesiccantDehumidifier = false;
3105 : }
3106 :
3107 0 : int WhichDesicDehum = Util::FindItemInList(DesicDehumName, state.dataDesiccantDehumidifiers->DesicDehum);
3108 0 : if (WhichDesicDehum != 0) {
3109 0 : return state.dataDesiccantDehumidifiers->DesicDehum(WhichDesicDehum).ProcAirInNode;
3110 : } else {
3111 0 : ShowSevereError(state, format("GetProcAirInletNodeNum: Could not find Desciccant Dehumidifier = \"{}\"", DesicDehumName));
3112 0 : ErrorsFound = true;
3113 0 : return 0;
3114 : }
3115 : }
3116 :
3117 0 : int GetProcAirOutletNodeNum(EnergyPlusData &state, std::string const &DesicDehumName, bool &ErrorsFound)
3118 : {
3119 : // FUNCTION INFORMATION:
3120 : // AUTHOR Lixing Gu
3121 : // DATE WRITTEN May 2019
3122 :
3123 : // PURPOSE OF THIS FUNCTION:
3124 : // This function looks up the given Desiccant Dehumidifier and returns the process air outlet node number.
3125 : // If incorrect Desiccant Dehumidifier name is given, ErrorsFound is returned as true and node number as zero.
3126 :
3127 : // Obtains and Allocates heat exchanger related parameters from input file
3128 0 : if (state.dataDesiccantDehumidifiers->GetInputDesiccantDehumidifier) {
3129 0 : GetDesiccantDehumidifierInput(state);
3130 0 : state.dataDesiccantDehumidifiers->GetInputDesiccantDehumidifier = false;
3131 : }
3132 :
3133 0 : int WhichDesicDehum = Util::FindItemInList(DesicDehumName, state.dataDesiccantDehumidifiers->DesicDehum);
3134 0 : if (WhichDesicDehum != 0) {
3135 0 : return state.dataDesiccantDehumidifiers->DesicDehum(WhichDesicDehum).ProcAirOutNode;
3136 : } else {
3137 0 : ShowSevereError(state, format("GetProcAirInletNodeNum: Could not find Desciccant Dehumidifier = \"{}\"", DesicDehumName));
3138 0 : ErrorsFound = true;
3139 0 : return 0;
3140 : }
3141 : }
3142 :
3143 : // End of Reporting subroutines for the SimAir Module
3144 : // *****************************************************************************
3145 :
3146 : // COPYRIGHT NOTICE
3147 :
3148 : // Portions Copyright (c) Gas Research Institute 2001. All rights reserved.
3149 :
3150 : // GRI LEGAL NOTICE
3151 : // Neither GRI, members of GRI nor any person or organization acting on behalf
3152 : // of either:
3153 :
3154 : // A. Makes any warranty of representation, express or implied with respect to
3155 : // the accuracy, completness, or usefulness of the information contained in
3156 : // in this program, including any warranty of merchantability or fitness of
3157 : // any purpose with respoect to the program, or that the use of any
3158 : // information disclosed in this program may not infringe privately-owned
3159 : // rights, or
3160 :
3161 : // B. Assumes any liability with respoct to the use of, or for any and all
3162 : // damages resulting from the use of the program or any portion thereof or
3163 : // any information disclosed therein.
3164 :
3165 : } // namespace DesiccantDehumidifiers
3166 :
3167 : } // namespace EnergyPlus
|