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