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