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/Fmath.hh>
53 :
54 : // EnergyPlus Headers
55 : #include <EnergyPlus/CurveManager.hh>
56 : #include <EnergyPlus/Data/EnergyPlusData.hh>
57 : #include <EnergyPlus/DataContaminantBalance.hh>
58 : #include <EnergyPlus/DataEnvironment.hh>
59 : #include <EnergyPlus/DataHVACGlobals.hh>
60 : #include <EnergyPlus/DataLoopNode.hh>
61 : #include <EnergyPlus/DataWater.hh>
62 : #include <EnergyPlus/DataZoneEnergyDemands.hh>
63 : #include <EnergyPlus/DataZoneEquipment.hh>
64 : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
65 : #include <EnergyPlus/NodeInputManager.hh>
66 : #include <EnergyPlus/OutputProcessor.hh>
67 : #include <EnergyPlus/Psychrometrics.hh>
68 : #include <EnergyPlus/ScheduleManager.hh>
69 : #include <EnergyPlus/UtilityRoutines.hh>
70 : #include <EnergyPlus/WaterManager.hh>
71 : #include <EnergyPlus/ZoneDehumidifier.hh>
72 :
73 : namespace EnergyPlus {
74 :
75 : namespace ZoneDehumidifier {
76 :
77 : // Module containing the routines dealing with the ZoneDehumidifier
78 :
79 : // MODULE INFORMATION:
80 : // AUTHOR Don Shirey, FSEC
81 : // DATE WRITTEN July/Aug 2009
82 : // MODIFIED na
83 : // RE-ENGINEERED na
84 :
85 : // PURPOSE OF THIS MODULE:
86 : // Calculate the performance of zone (room) air dehumidifiers. Meant to model
87 : // conventional direct expansion (DX) cooling-based room air dehumidifiers
88 : // (reject 100% of condenser heat to the zone air), but the approach
89 : // might be able to be used to model other room air dehumidifier types.
90 :
91 : // METHODOLOGY EMPLOYED:
92 : // Model as a piece of zone equipment, with inputs for water removal and
93 : // energy factor at rated conditions (26.7C, 60% RH). Then provide curve objects
94 : // to describe performance at off-rated conditions. A part-load cycling curve
95 : // input is also provided. It is assumed that this equipment dehumidifies but
96 : // heats the air. If used in tandem with another system that cools and dehumidifies,
97 : // then the zone dehumidifier should be specified as the lowest cooling priority
98 : // in the ZoneHVAC:EquipmentList object. The cooling and dehumidification system
99 : // operates first to meet the temperature setpoint (and possibly the high humidity
100 : // setpoint as well). If additional dehumidification is needed, then the zone
101 : // dehumidifier operates. The excess sensible heat generated by the dehumidifier
102 : // is carried over to the next HVAC time step.
103 :
104 : // OTHER NOTES:
105 : // Example manufacturer's data at:
106 : // http://www.thermastor.com/HI-E-DRY-100/HI-E-DRY-100-Spec.pdf
107 : // http://www.thermastor.com/HI-E-DRY-195/HI-E-DRY-195-Spec.pdf
108 :
109 : // Using/Aliasing
110 : using namespace DataLoopNode;
111 : using namespace ScheduleManager;
112 :
113 50989 : void SimZoneDehumidifier(EnergyPlusData &state,
114 : std::string const &CompName, // Name of the zone dehumidifier
115 : int const ZoneNum, // Number of zone being served
116 : [[maybe_unused]] bool const FirstHVACIteration, // TRUE if 1st HVAC simulation of system timestep
117 : Real64 &QSensOut, // Sensible capacity delivered to zone (W)
118 : Real64 &QLatOut, // Latent capacity delivered to zone (kg/s), dehumidify = negative
119 : int &CompIndex // Index to the zone dehumidifier
120 : )
121 : {
122 :
123 : // SUBROUTINE INFORMATION:
124 : // AUTHOR Don Shirey, FSEC
125 : // DATE WRITTEN July/Aug 2009
126 : // MODIFIED na
127 : // RE-ENGINEERED na
128 :
129 : // PURPOSE OF THIS SUBROUTINE:
130 : // Simulate a zone dehumidifier.
131 :
132 : // METHODOLOGY EMPLOYED:
133 : // Call appropriate subroutines to get input values, initialize variables, model performanc
134 : // update node information, report model outputs.
135 :
136 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
137 : int ZoneDehumidNum; // Index of zone dehumidifier being simulated
138 : Real64 QZnDehumidReq; // Zone dehumidification load required (kg moisture/sec)
139 :
140 50989 : if (state.dataZoneDehumidifier->GetInputFlag) {
141 2 : GetZoneDehumidifierInput(state);
142 2 : state.dataZoneDehumidifier->GetInputFlag = false;
143 : }
144 :
145 : // Find the correct zone dehumidifier
146 50989 : if (CompIndex == 0) {
147 2 : ZoneDehumidNum = Util::FindItemInList(CompName, state.dataZoneDehumidifier->ZoneDehumid);
148 2 : if (ZoneDehumidNum == 0) {
149 0 : ShowFatalError(state, format("SimZoneDehumidifier: Unit not found= {}", CompName));
150 : }
151 2 : CompIndex = ZoneDehumidNum;
152 : } else {
153 50987 : ZoneDehumidNum = CompIndex;
154 50987 : int NumDehumidifiers = (int)state.dataZoneDehumidifier->ZoneDehumid.size();
155 50987 : if (ZoneDehumidNum > NumDehumidifiers || ZoneDehumidNum < 1) {
156 0 : ShowFatalError(state,
157 0 : format("SimZoneDehumidifier: Invalid CompIndex passed= {}, Number of Units= {}, Entered Unit name= {}",
158 : ZoneDehumidNum,
159 : NumDehumidifiers,
160 : CompName));
161 : }
162 50987 : if (state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidNum).CheckEquipName) {
163 2 : if (CompName != state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidNum).Name) {
164 0 : ShowFatalError(state,
165 0 : format("SimZoneDehumidifier: Invalid CompIndex passed={}, Unit name= {}, stored Unit Name for that index= {}",
166 : ZoneDehumidNum,
167 : CompName,
168 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidNum).Name));
169 : }
170 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidNum).CheckEquipName = false;
171 : }
172 : }
173 :
174 50989 : QZnDehumidReq = state.dataZoneEnergyDemand->ZoneSysMoistureDemand(ZoneNum).RemainingOutputReqToDehumidSP; // Negative means dehumidify
175 :
176 50989 : InitZoneDehumidifier(state, ZoneDehumidNum);
177 :
178 50989 : CalcZoneDehumidifier(state, ZoneDehumidNum, QZnDehumidReq, QSensOut, QLatOut);
179 :
180 50989 : UpdateZoneDehumidifier(state, ZoneDehumidNum);
181 :
182 50989 : ReportZoneDehumidifier(state, ZoneDehumidNum);
183 50989 : }
184 :
185 24 : void GetZoneDehumidifierInput(EnergyPlusData &state)
186 : {
187 :
188 : // SUBROUTINE INFORMATION:
189 : // AUTHOR Don Shirey, FSEC
190 : // DATE WRITTEN July/Aug 2009
191 : // MODIFIED na
192 : // RE-ENGINEERED na
193 :
194 : // PURPOSE OF THIS SUBROUTINE:
195 : // Retrieve the inputs from the input data file (idf) being simulated.
196 :
197 : // METHODOLOGY EMPLOYED:
198 : // Standard EnergyPlus methodology using available utility routines where appropriate.
199 :
200 : // Using/Aliasing
201 : using Curve::CurveValue;
202 : using Curve::GetCurveIndex;
203 : using NodeInputManager::GetOnlySingleNode;
204 : using WaterManager::SetupTankSupplyComponent;
205 :
206 : // SUBROUTINE PARAMETER DEFINITIONS:
207 : static constexpr std::string_view RoutineName("GetZoneDehumidifierInput");
208 24 : static std::string const CurrentModuleObject("ZoneHVAC:Dehumidifier:DX");
209 24 : Real64 constexpr RatedInletAirTemp(26.7);
210 24 : Real64 constexpr RatedInletAirRH(60.0);
211 :
212 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
213 : int ZoneDehumidIndex; // Loop index
214 24 : int NumAlphas(0); // Number of Alphas to allocate arrays, then used for each GetObjectItem call
215 24 : int NumNumbers(0); // Number of Numbers to allocate arrays, then used for each GetObjectItem call
216 : int IOStatus; // Used in GetObjectItem
217 24 : bool ErrorsFound(false); // Set to true if errors in input, fatal at end of routine
218 24 : Array1D_string Alphas; // Alpha input items for object
219 24 : Array1D_string cAlphaFields; // Alpha field names
220 24 : Array1D_string cNumericFields; // Numeric field names
221 24 : Array1D<Real64> Numbers; // Numeric input items for object
222 24 : Array1D_bool lAlphaBlanks; // Logical array, alpha field input BLANK = .TRUE.
223 24 : Array1D_bool lNumericBlanks; // Logical array, numeric field input BLANK = .TRUE.
224 24 : int TotalArgs(0); // Total number of alpha and numeric arguments (max)
225 : Real64 CurveVal; // Output from curve object (water removal or energy factor curves)
226 :
227 24 : int NumDehumidifiers = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
228 :
229 24 : state.dataZoneDehumidifier->ZoneDehumid.allocate(NumDehumidifiers);
230 :
231 24 : state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, TotalArgs, NumAlphas, NumNumbers);
232 :
233 24 : Alphas.allocate(NumAlphas);
234 24 : cAlphaFields.allocate(NumAlphas);
235 24 : cNumericFields.allocate(NumNumbers);
236 24 : Numbers.dimension(NumNumbers, 0.0);
237 24 : lAlphaBlanks.dimension(NumAlphas, true);
238 24 : lNumericBlanks.dimension(NumNumbers, true);
239 :
240 26 : for (ZoneDehumidIndex = 1; ZoneDehumidIndex <= NumDehumidifiers; ++ZoneDehumidIndex) {
241 :
242 2 : state.dataInputProcessing->inputProcessor->getObjectItem(state,
243 : CurrentModuleObject,
244 : ZoneDehumidIndex,
245 : Alphas,
246 : NumAlphas,
247 : Numbers,
248 : NumNumbers,
249 : IOStatus,
250 : lNumericBlanks,
251 : lAlphaBlanks,
252 : cAlphaFields,
253 : cNumericFields);
254 2 : Util::IsNameEmpty(state, Alphas(1), CurrentModuleObject, ErrorsFound);
255 :
256 : // A1, \field Name
257 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name = Alphas(1);
258 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).UnitType = CurrentModuleObject; // 'ZoneHVAC:Dehumidifier:DX'
259 :
260 : // A2, \field Availability Schedule Name
261 2 : if (lAlphaBlanks(2)) {
262 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).SchedPtr = ScheduleManager::ScheduleAlwaysOn;
263 : } else {
264 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).SchedPtr =
265 2 : GetScheduleIndex(state, Alphas(2)); // Convert schedule name to pointer
266 2 : if (state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).SchedPtr == 0) {
267 0 : ShowSevereError(state, format("{} not found = {}", cAlphaFields(2), Alphas(2)));
268 0 : ShowContinueError(
269 0 : state, format("Occurs in {} = {}", CurrentModuleObject, state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name));
270 0 : ErrorsFound = true;
271 : }
272 : }
273 :
274 : // A3 , \field Air Inlet Node Name
275 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).AirInletNodeNum =
276 4 : GetOnlySingleNode(state,
277 2 : Alphas(3),
278 : ErrorsFound,
279 : DataLoopNode::ConnectionObjectType::ZoneHVACDehumidifierDX,
280 2 : Alphas(1),
281 : DataLoopNode::NodeFluidType::Air,
282 : DataLoopNode::ConnectionType::Inlet,
283 : NodeInputManager::CompFluidStream::Primary,
284 : ObjectIsNotParent);
285 :
286 : // A4 , \field Air Outlet Node Name
287 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).AirOutletNodeNum =
288 4 : GetOnlySingleNode(state,
289 2 : Alphas(4),
290 : ErrorsFound,
291 : DataLoopNode::ConnectionObjectType::ZoneHVACDehumidifierDX,
292 2 : Alphas(1),
293 : DataLoopNode::NodeFluidType::Air,
294 : DataLoopNode::ConnectionType::Outlet,
295 : NodeInputManager::CompFluidStream::Primary,
296 : ObjectIsNotParent);
297 :
298 : // N1, \field Rated Water Removal
299 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).RatedWaterRemoval = Numbers(1);
300 2 : if (state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).RatedWaterRemoval <= 0.0) {
301 0 : ShowSevereError(state, format("{} must be greater than zero.", cNumericFields(1)));
302 0 : ShowContinueError(state, format("Value specified = {:.5T}", Numbers(1)));
303 0 : ShowContinueError(state,
304 0 : format("Occurs in {} = {}", CurrentModuleObject, state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name));
305 0 : ErrorsFound = true;
306 : }
307 :
308 : // N2, \field Rated Energy Factor
309 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).RatedEnergyFactor = Numbers(2);
310 2 : if (state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).RatedEnergyFactor <= 0.0) {
311 0 : ShowSevereError(state, format("{} must be greater than zero.", cNumericFields(2)));
312 0 : ShowContinueError(state, format("Value specified = {:.5T}", Numbers(2)));
313 0 : ShowContinueError(state,
314 0 : format("Occurs in {} = {}", CurrentModuleObject, state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name));
315 0 : ErrorsFound = true;
316 : }
317 :
318 : // N3, \field Rated Air Flow Rate
319 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).RatedAirVolFlow = Numbers(3);
320 2 : if (state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).RatedAirVolFlow <= 0.0) {
321 0 : ShowSevereError(state, format("{} must be greater than zero.", cNumericFields(3)));
322 0 : ShowContinueError(state, format("Value specified = {:.5T}", Numbers(3)));
323 0 : ShowContinueError(state,
324 0 : format("Occurs in {} = {}", CurrentModuleObject, state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name));
325 0 : ErrorsFound = true;
326 : }
327 :
328 : // A5, \field Water Removal Curve Name
329 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).WaterRemovalCurveIndex =
330 2 : GetCurveIndex(state, Alphas(5)); // Convert curve name to index number
331 2 : if (state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).WaterRemovalCurveIndex == 0) {
332 0 : if (lAlphaBlanks(5)) {
333 0 : ShowSevereError(state,
334 0 : format("{}:{}=\"{}\" is required, missing for {} = {}",
335 : RoutineName,
336 : CurrentModuleObject,
337 : cAlphaFields(5),
338 : cAlphaFields(1),
339 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name));
340 : } else {
341 0 : ShowSevereError(state, format("{} not found = {}", cAlphaFields(5), Alphas(5)));
342 0 : ShowContinueError(
343 0 : state, format("Occurs in {} = {}", CurrentModuleObject, state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name));
344 : }
345 0 : ErrorsFound = true;
346 : } else {
347 : // Verify Curve object, only legal type is BiQuadratic
348 4 : ErrorsFound |= Curve::CheckCurveDims(state,
349 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).WaterRemovalCurveIndex, // Curve index
350 : {2}, // Valid dimensions
351 : RoutineName, // Routine name
352 : CurrentModuleObject, // Object Type
353 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name, // Object Name
354 2 : cAlphaFields(5)); // Field Name
355 :
356 2 : if (!ErrorsFound) {
357 4 : CurveVal = CurveValue(
358 2 : state, state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).WaterRemovalCurveIndex, RatedInletAirTemp, RatedInletAirRH);
359 2 : if (CurveVal > 1.10 || CurveVal < 0.90) {
360 0 : ShowWarningError(state, format("{} output is not equal to 1.0", cAlphaFields(5)));
361 0 : ShowContinueError(state, format("(+ or -10%) at rated conditions for {} = {}", CurrentModuleObject, Alphas(1)));
362 0 : ShowContinueError(state, format("Curve output at rated conditions = {:.3T}", CurveVal));
363 : }
364 : }
365 : }
366 :
367 : // A6, \field Energy Factor Curve Name
368 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).EnergyFactorCurveIndex =
369 2 : GetCurveIndex(state, Alphas(6)); // convert curve name to number
370 2 : if (state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).EnergyFactorCurveIndex == 0) {
371 0 : if (lAlphaBlanks(6)) {
372 0 : ShowSevereError(state,
373 0 : format("{}:{}=\"{}\" is required, missing for {} = {}",
374 : RoutineName,
375 : CurrentModuleObject,
376 : cAlphaFields(6),
377 : cAlphaFields(1),
378 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name));
379 : } else {
380 0 : ShowSevereError(state, format("{} not found = {}", cAlphaFields(6), Alphas(6)));
381 0 : ShowContinueError(
382 0 : state, format("Occurs in {} = {}", CurrentModuleObject, state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name));
383 : }
384 0 : ErrorsFound = true;
385 : } else {
386 : // Verify Curve Object, only legal type is BiQuadratic
387 4 : ErrorsFound |= Curve::CheckCurveDims(state,
388 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).EnergyFactorCurveIndex, // Curve index
389 : {2}, // Valid dimensions
390 : RoutineName, // Routine name
391 : CurrentModuleObject, // Object Type
392 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name, // Object Name
393 2 : cAlphaFields(6)); // Field Name
394 :
395 2 : if (!ErrorsFound) {
396 4 : CurveVal = CurveValue(
397 2 : state, state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).EnergyFactorCurveIndex, RatedInletAirTemp, RatedInletAirRH);
398 2 : if (CurveVal > 1.10 || CurveVal < 0.90) {
399 0 : ShowWarningError(state, format("{} output is not equal to 1.0", cAlphaFields(6)));
400 0 : ShowContinueError(state, format("(+ or -10%) at rated conditions for {} = {}", CurrentModuleObject, Alphas(1)));
401 0 : ShowContinueError(state, format("Curve output at rated conditions = {:.3T}", CurveVal));
402 : }
403 : }
404 : }
405 :
406 : // A7, \field Part Load Fraction Correlation Curve Name
407 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).PartLoadCurveIndex =
408 2 : GetCurveIndex(state, Alphas(7)); // convert curve name to number
409 2 : if (state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).PartLoadCurveIndex == 0) {
410 0 : if (lAlphaBlanks(7)) {
411 0 : ShowSevereError(state,
412 0 : format("{}:{}=\"{}\" is required, missing for {} = {}",
413 : RoutineName,
414 : CurrentModuleObject,
415 : cAlphaFields(7),
416 : cAlphaFields(1),
417 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name));
418 : } else {
419 0 : ShowSevereError(state, format("{} not found = {}", cAlphaFields(7), Alphas(7)));
420 0 : ShowContinueError(
421 0 : state, format("Occurs in {} = {}", CurrentModuleObject, state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name));
422 : }
423 0 : ErrorsFound = true;
424 : } else {
425 : // Verify Curve Object, legal types are Quadratic and Cubic
426 4 : ErrorsFound |= Curve::CheckCurveDims(state,
427 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).PartLoadCurveIndex, // Curve index
428 : {1}, // Valid dimensions
429 : RoutineName, // Routine name
430 : CurrentModuleObject, // Object Type
431 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name, // Object Name
432 2 : cAlphaFields(7)); // Field Name
433 : }
434 :
435 : // N4, \field Minimum Dry-Bulb Temperature for Dehumidifier Operation
436 : // N5, \field Maximum Dry-Bulb Temperature for Dehumidifier Operation
437 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).MinInletAirTemp = Numbers(4);
438 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).MaxInletAirTemp = Numbers(5);
439 :
440 2 : if (state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).MinInletAirTemp >=
441 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).MaxInletAirTemp) {
442 0 : ShowSevereError(state, format("{} must be greater than {}", cNumericFields(5), cNumericFields(4)));
443 0 : ShowContinueError(state, format("{} specified = {:.1T}", cNumericFields(5), Numbers(5)));
444 0 : ShowContinueError(state, format("{} specified = {:.1T}", cNumericFields(4), Numbers(4)));
445 0 : ShowContinueError(state,
446 0 : format("Occurs in {} = {}", CurrentModuleObject, state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name));
447 0 : ErrorsFound = true;
448 : }
449 :
450 : // N6, \field Off Cycle Parasitic Electric Load
451 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).OffCycleParasiticLoad = Numbers(6); // Off Cycle Parasitic Load [W]
452 :
453 2 : if (state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).OffCycleParasiticLoad < 0.0) {
454 0 : ShowSevereError(state, format("{} must be >= zero.", cNumericFields(6)));
455 0 : ShowContinueError(state, format("Value specified = {:.2T}", Numbers(6)));
456 0 : ShowContinueError(state,
457 0 : format("Occurs in {} = {}", CurrentModuleObject, state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name));
458 0 : ErrorsFound = true;
459 : }
460 :
461 : // A8; \field Condensate Collection Water Storage Tank Name
462 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).CondensateCollectName = Alphas(8);
463 2 : if (lAlphaBlanks(8)) {
464 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).CondensateCollectMode = CondensateOutlet::Discarded;
465 : } else {
466 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).CondensateCollectMode = CondensateOutlet::ToTank;
467 0 : SetupTankSupplyComponent(state,
468 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name,
469 : CurrentModuleObject,
470 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).CondensateCollectName,
471 : ErrorsFound,
472 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).CondensateTankID,
473 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).CondensateTankSupplyARRID);
474 : }
475 :
476 : } // DO ZoneDehumidIndex=1,NumDehumidifiers
477 :
478 24 : Alphas.deallocate();
479 24 : cAlphaFields.deallocate();
480 24 : cNumericFields.deallocate();
481 24 : Numbers.deallocate();
482 24 : lAlphaBlanks.deallocate();
483 24 : lNumericBlanks.deallocate();
484 :
485 24 : if (ErrorsFound) {
486 0 : ShowFatalError(state, format("{}:{}: Errors found in input.", RoutineName, CurrentModuleObject));
487 : }
488 :
489 26 : for (ZoneDehumidIndex = 1; ZoneDehumidIndex <= NumDehumidifiers; ++ZoneDehumidIndex) {
490 : // Set up report variables for the dehumidifiers
491 4 : SetupOutputVariable(state,
492 : "Zone Dehumidifier Sensible Heating Rate",
493 : Constant::Units::W,
494 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).SensHeatingRate,
495 : OutputProcessor::TimeStepType::System,
496 : OutputProcessor::StoreType::Average,
497 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name);
498 4 : SetupOutputVariable(state,
499 : "Zone Dehumidifier Sensible Heating Energy",
500 : Constant::Units::J,
501 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).SensHeatingEnergy,
502 : OutputProcessor::TimeStepType::System,
503 : OutputProcessor::StoreType::Sum,
504 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name);
505 4 : SetupOutputVariable(state,
506 : "Zone Dehumidifier Removed Water Mass Flow Rate",
507 : Constant::Units::kg_s,
508 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).WaterRemovalRate,
509 : OutputProcessor::TimeStepType::System,
510 : OutputProcessor::StoreType::Average,
511 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name);
512 4 : SetupOutputVariable(state,
513 : "Zone Dehumidifier Removed Water Mass",
514 : Constant::Units::kg,
515 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).WaterRemoved,
516 : OutputProcessor::TimeStepType::System,
517 : OutputProcessor::StoreType::Sum,
518 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name);
519 4 : SetupOutputVariable(state,
520 : "Zone Dehumidifier Electricity Rate",
521 : Constant::Units::W,
522 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).ElecPower,
523 : OutputProcessor::TimeStepType::System,
524 : OutputProcessor::StoreType::Average,
525 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name);
526 4 : SetupOutputVariable(state,
527 : "Zone Dehumidifier Electricity Energy",
528 : Constant::Units::J,
529 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).ElecConsumption,
530 : OutputProcessor::TimeStepType::System,
531 : OutputProcessor::StoreType::Sum,
532 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name,
533 : Constant::eResource::Electricity,
534 : OutputProcessor::Group::HVAC,
535 : OutputProcessor::EndUseCat::Cooling);
536 4 : SetupOutputVariable(state,
537 : "Zone Dehumidifier Off Cycle Parasitic Electricity Rate",
538 : Constant::Units::W,
539 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).OffCycleParasiticElecPower,
540 : OutputProcessor::TimeStepType::System,
541 : OutputProcessor::StoreType::Average,
542 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name);
543 4 : SetupOutputVariable(state,
544 : "Zone Dehumidifier Off Cycle Parasitic Electricity Energy",
545 : Constant::Units::J,
546 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).OffCycleParasiticElecCons,
547 : OutputProcessor::TimeStepType::System,
548 : OutputProcessor::StoreType::Sum,
549 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name);
550 4 : SetupOutputVariable(state,
551 : "Zone Dehumidifier Part Load Ratio",
552 : Constant::Units::None,
553 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).DehumidPLR,
554 : OutputProcessor::TimeStepType::System,
555 : OutputProcessor::StoreType::Average,
556 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name);
557 4 : SetupOutputVariable(state,
558 : "Zone Dehumidifier Runtime Fraction",
559 : Constant::Units::None,
560 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).DehumidRTF,
561 : OutputProcessor::TimeStepType::System,
562 : OutputProcessor::StoreType::Average,
563 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name);
564 4 : SetupOutputVariable(state,
565 : "Zone Dehumidifier Outlet Air Temperature",
566 : Constant::Units::C,
567 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).OutletAirTemp,
568 : OutputProcessor::TimeStepType::System,
569 : OutputProcessor::StoreType::Average,
570 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name);
571 :
572 2 : if (state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).CondensateCollectMode == CondensateOutlet::ToTank) {
573 0 : SetupOutputVariable(state,
574 : "Zone Dehumidifier Condensate Volume Flow Rate",
575 : Constant::Units::m3_s,
576 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).DehumidCondVolFlowRate,
577 : OutputProcessor::TimeStepType::System,
578 : OutputProcessor::StoreType::Average,
579 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name);
580 0 : SetupOutputVariable(state,
581 : "Zone Dehumidifier Condensate Volume",
582 : Constant::Units::m3,
583 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).DehumidCondVol,
584 : OutputProcessor::TimeStepType::System,
585 : OutputProcessor::StoreType::Sum,
586 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name,
587 : Constant::eResource::OnSiteWater,
588 : OutputProcessor::Group::HVAC,
589 : OutputProcessor::EndUseCat::Condensate);
590 : }
591 : }
592 24 : }
593 :
594 50989 : void InitZoneDehumidifier(EnergyPlusData &state, int const ZoneDehumNum) // Number of the current zone dehumidifier being simulated
595 : {
596 :
597 : // SUBROUTINE INFORMATION:
598 : // AUTHOR Don Shirey, FSEC
599 : // DATE WRITTEN July/Aug 2009
600 : // MODIFIED na
601 : // RE-ENGINEERED na
602 :
603 : // PURPOSE OF THIS SUBROUTINE:
604 : // This subroutine initializes information for the zone dehumidifier model
605 :
606 : // METHODOLOGY EMPLOYED:
607 : // Use status flags to trigger various initializations
608 :
609 : // Using/Aliasing
610 : using DataZoneEquipment::CheckZoneEquipmentList;
611 : using Psychrometrics::PsyRhoAirFnPbTdbW;
612 : using Psychrometrics::PsyWFnTdbRhPb;
613 :
614 : // SUBROUTINE PARAMETER DEFINITIONS:
615 : static constexpr std::string_view RoutineName("InitZoneDehumidifier");
616 :
617 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
618 : int AirInletNode; // Inlet air node number
619 : Real64 RatedAirHumrat; // Humidity ratio (kg/kg) at rated inlet air conditions of 26.6667C, 60% RH
620 : Real64 RatedAirDBTemp; // Dry-bulb air temperature at rated conditions 26.6667C
621 : Real64 RatedAirRH; // Relative humidity of air (0.6 --> 60%) at rated conditions
622 :
623 : // Need to check all dehumidifiers to see if they are on Zone Equipment List or issue warning
624 50989 : if (!state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).ZoneEquipmentListChecked && state.dataZoneEquip->ZoneEquipInputsFilled) {
625 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).ZoneEquipmentListChecked = true;
626 4 : if (!CheckZoneEquipmentList(state,
627 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).UnitType,
628 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).Name)) {
629 0 : ShowSevereError(
630 : state,
631 0 : format("InitZoneDehumidifier: Zone Dehumidifier=\"{},{}\" is not on any ZoneHVAC:EquipmentList. It will not be simulated.",
632 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).UnitType,
633 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).Name));
634 : }
635 : }
636 :
637 50989 : AirInletNode = state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).AirInletNodeNum;
638 : // Do the Begin Environment initializations
639 50989 : if (state.dataGlobal->BeginEnvrnFlag && state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).MyEnvrnFlag) {
640 :
641 : // Set the mass flow rates from the input volume flow rates, at rated conditions of 26.6667C, 60% RH
642 : // Might default back to STP later after discussion with M. Witte, use StdRhoAir instead of calc'd RhoAir at rated conditions
643 11 : RatedAirDBTemp = 26.6667; // 26.6667 C, 80F
644 11 : RatedAirRH = 0.6; // 60% RH
645 11 : RatedAirHumrat = PsyWFnTdbRhPb(state, RatedAirDBTemp, RatedAirRH, state.dataEnvrn->StdBaroPress, RoutineName);
646 11 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).RatedAirMassFlow =
647 11 : PsyRhoAirFnPbTdbW(state, state.dataEnvrn->StdBaroPress, RatedAirDBTemp, RatedAirHumrat, RoutineName) *
648 11 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).RatedAirVolFlow;
649 :
650 : // Set the node max and min mass flow rates on inlet node... outlet node gets updated in UPDATE subroutine
651 11 : state.dataLoopNodes->Node(AirInletNode).MassFlowRateMax = state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).RatedAirMassFlow;
652 11 : state.dataLoopNodes->Node(AirInletNode).MassFlowRateMaxAvail = state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).RatedAirMassFlow;
653 11 : state.dataLoopNodes->Node(AirInletNode).MassFlowRateMinAvail = 0.0;
654 11 : state.dataLoopNodes->Node(AirInletNode).MassFlowRateMin = 0.0;
655 :
656 11 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).MyEnvrnFlag = false;
657 : } // End one time inits
658 :
659 50989 : if (!state.dataGlobal->BeginEnvrnFlag) {
660 50749 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).MyEnvrnFlag = true;
661 : }
662 :
663 : // These initializations are done every iteration
664 50989 : state.dataLoopNodes->Node(AirInletNode).MassFlowRate = state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).RatedAirMassFlow;
665 :
666 : // Zero out the report variables
667 50989 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).SensHeatingRate = 0.0; // Zone Dehumidifier Sensible Heating Rate [W]
668 50989 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).SensHeatingEnergy = 0.0; // Zone Dehumidifier Sensible Heating Energy [J]
669 50989 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).WaterRemovalRate = 0.0; // Zone Dehumidifier Water Removal Rate [kg/s]
670 50989 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).WaterRemoved = 0.0; // Zone Dehumidifier Water Removed [kg]
671 50989 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).ElecPower = 0.0; // Zone Dehumidifier Electric Power [W]
672 50989 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).ElecConsumption = 0.0; // Zone Dehumidifier Electric Consumption [J]
673 50989 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).DehumidPLR = 0.0; // Zone Dehumidifier Part-Load Ratio [-]
674 50989 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).DehumidRTF = 0.0; // Zone Dehumidifier Runtime Fraction [-]
675 50989 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).OffCycleParasiticElecPower =
676 : 0.0; // Zone Dehumidifier Off-Cycle Parasitic Electric Power [W]
677 50989 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).OffCycleParasiticElecCons =
678 : 0.0; // Zone Dehumidifier Off-Cycle Parasitic Electric Consumption [J]
679 50989 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).DehumidCondVolFlowRate =
680 : 0.0; // Zone Dehumidifier Condensate Volumetric Flow Rate [m3/s]
681 50989 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).DehumidCondVol = 0.0; // Zone Dehumidifier Condensate Volume [m3]
682 50989 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).OutletAirTemp =
683 50989 : state.dataLoopNodes->Node(AirInletNode).Temp; // Zone Dehumidifier Outlet Air Temperature [C]
684 50989 : }
685 :
686 50989 : void CalcZoneDehumidifier(EnergyPlusData &state,
687 : int const ZoneDehumNum, // Index number of the current zone dehumidifier being simulated
688 : Real64 const QZnDehumidReq, // Dehumidification load to be met (kg/s), negative value means dehumidification load
689 : Real64 &SensibleOutput, // Sensible (heating) output (W), sent to load predictor for next simulation time step
690 : Real64 &LatentOutput // Latent (dehumidification) output provided (kg/s)
691 : )
692 : {
693 :
694 : // SUBROUTINE INFORMATION:
695 : // AUTHOR Don Shirey, FSEC
696 : // DATE WRITTEN July/Aug 2009
697 : // MODIFIED na
698 : // RE-ENGINEERED na
699 :
700 : // PURPOSE OF THIS SUBROUTINE:
701 : // Calculate the delivered capacity, electric energy consumption and water/condensate
702 : // removal rates for the zone dehumidifier.
703 :
704 : // METHODOLOGY EMPLOYED:
705 : // Cycle the dehumidifier as needed to meet the remaining zone dehumidification load.
706 : // Send excess sensible heat to zone energy balance (via SensibleOutput) for next HVAC time step,
707 : // so set the dehumidifier outlet air temp = inlet air temp to avoid double counting excess sensible.
708 :
709 : // REFERENCES:
710 : // na
711 :
712 : // Using/Aliasing
713 : using Curve::CurveValue;
714 : using Psychrometrics::PsyCpAirFnW;
715 : using Psychrometrics::PsyHfgAirFnWTdb;
716 : using Psychrometrics::PsyHFnTdbW;
717 : using Psychrometrics::PsyRhFnTdbWPb;
718 : using Psychrometrics::RhoH2O;
719 :
720 : // Locals
721 : // SUBROUTINE ARGUMENT DEFINITIONS:
722 :
723 : // SUBROUTINE PARAMETER DEFINITIONS:
724 : static constexpr std::string_view RoutineName("CalcZoneDehumidifier");
725 :
726 : // INTERFACE BLOCK SPECIFICATIONS:
727 : // na
728 :
729 : // DERIVED TYPE DEFINITIONS:
730 : // na
731 :
732 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
733 : Real64 WaterRemovalRateFactor; // Adjustment to Rate Water Removal as a function of inlet air T and RH
734 : Real64 WaterRemovalVolRate; // Actual water removal rate at current inlet air conditions (L/day)
735 : Real64 WaterRemovalMassRate; // Actual water removal rate at current inlet air conditions (kg/s)
736 : Real64 EnergyFactorAdjFactor; // Adjustment to Rate Energy Factor as a function of inlet air T and RH
737 : Real64 EnergyFactor; // Actual Energy Factor as a function of inlet air T and RH
738 : Real64 InletAirTemp; // Dry-bulb temperature of air entering the dehumidifier (C)
739 : Real64 InletAirHumRat; // Humidity ratio of the air entering the dehumidifier (kg/kg)
740 : Real64 InletAirRH; // Relative humidity of air entering the dehumidifier (%)
741 : Real64 OutletAirTemp; // Dry-bulb temperature of air leaving the dehumidifier (C)
742 : Real64 OutletAirHumRat; // Humidity ratio of air leaving the dehumidifier (kg/kg)
743 : Real64 PLR; // Part-load ratio = (dehumid load to be met)/(dehumid capacity of the dehumidifier)
744 : Real64 PLF; // Part-load fraction (-), RuntimeFraction = PLR/PLF
745 : Real64 RunTimeFraction; // Dehumidifier runtime fraction (-)
746 : Real64 ElectricPowerOnCycle; // Electric power when dehumidifier is operating (W)
747 : Real64 ElectricPowerAvg; // Average electric power for this dehumidifier (W)
748 : Real64 hfg; // Enthalpy of evaporation of inlet air (J/kg)
749 : Real64 AirMassFlowRate; // Air mass flow rate through this dehumidifier (kg/s)
750 : Real64 Cp; // Heat capacity of inlet air (J/kg-C)
751 50989 : int AirInletNodeNum(0); // Node number for the inlet air to the dehumidifier
752 50989 : int AirOutletNodeNum(0); // Node number for the outlet air from the dehumidifier
753 :
754 50989 : SensibleOutput = 0.0;
755 50989 : LatentOutput = 0.0;
756 50989 : WaterRemovalRateFactor = 0.0;
757 50989 : AirMassFlowRate = 0.0;
758 50989 : PLR = 0.0;
759 50989 : PLF = 0.0;
760 50989 : EnergyFactorAdjFactor = 0.0;
761 50989 : RunTimeFraction = 0.0;
762 50989 : ElectricPowerAvg = 0.0;
763 50989 : ElectricPowerOnCycle = 0.0;
764 :
765 50989 : AirInletNodeNum = state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).AirInletNodeNum;
766 50989 : AirOutletNodeNum = state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).AirOutletNodeNum;
767 :
768 50989 : InletAirTemp = state.dataLoopNodes->Node(AirInletNodeNum).Temp;
769 50989 : InletAirHumRat = state.dataLoopNodes->Node(AirInletNodeNum).HumRat;
770 50989 : InletAirRH = 100.0 * PsyRhFnTdbWPb(state, InletAirTemp, InletAirHumRat, state.dataEnvrn->OutBaroPress, RoutineName); // RH in percent (%)
771 :
772 2371 : if (QZnDehumidReq < 0.0 && GetCurrentScheduleValue(state, state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).SchedPtr) > 0.0 &&
773 55731 : InletAirTemp >= state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).MinInletAirTemp &&
774 2371 : InletAirTemp <= state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).MaxInletAirTemp) {
775 : // A dehumidification load is being requested and dehumidifier is available (schedule value > 0)
776 : // and the inlet air temperature is within the min/max values specified by user input
777 :
778 2371 : WaterRemovalRateFactor =
779 2371 : CurveValue(state, state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).WaterRemovalCurveIndex, InletAirTemp, InletAirRH);
780 : // Warn user if curve output goes negative
781 2371 : if (WaterRemovalRateFactor <= 0.0) {
782 0 : if (state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).WaterRemovalCurveErrorCount < 1) {
783 0 : ++state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).WaterRemovalCurveErrorCount;
784 0 : ShowWarningError(state,
785 0 : format("{} \"{}\":",
786 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).UnitType,
787 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).Name));
788 0 : ShowContinueError(state, format(" Water Removal Rate Curve output is <= 0.0 ({:.5T}).", WaterRemovalRateFactor));
789 0 : ShowContinueError(
790 : state,
791 0 : format(
792 : " Negative value occurs using an inlet air dry-bulb temperature of {:.2T} and an inlet air relative humidity of {:.1T}.",
793 : InletAirTemp,
794 : InletAirRH));
795 0 : ShowContinueErrorTimeStamp(state, " Dehumidifier turned off for this time step but simulation continues.");
796 : } else {
797 0 : ShowRecurringWarningErrorAtEnd(state,
798 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).UnitType + " \"" +
799 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).Name +
800 : "\": Water Removal Rate Curve output is <= 0.0 warning continues...",
801 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).WaterRemovalCurveErrorIndex,
802 : WaterRemovalRateFactor,
803 : WaterRemovalRateFactor);
804 : }
805 0 : WaterRemovalRateFactor = 0.0;
806 : }
807 :
808 2371 : WaterRemovalVolRate = WaterRemovalRateFactor * state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).RatedWaterRemoval;
809 :
810 2371 : WaterRemovalMassRate =
811 2371 : WaterRemovalVolRate / (24.0 * Constant::SecInHour * 1000.0) *
812 2371 : RhoH2O(max((InletAirTemp - 11.0), 1.0)); //(L/d)/(24 hr/day *3600 sec/hr * 1000 L/m3) | Density of water, minimum temp = 1.0C
813 :
814 2371 : if (WaterRemovalMassRate > 0.0) {
815 2371 : PLR = max(0.0, min(1.0, -QZnDehumidReq / WaterRemovalMassRate));
816 : } else {
817 0 : PLR = 0.0;
818 0 : RunTimeFraction = 0.0;
819 : }
820 :
821 2371 : EnergyFactorAdjFactor =
822 2371 : CurveValue(state, state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).EnergyFactorCurveIndex, InletAirTemp, InletAirRH);
823 :
824 : // Warn user if curve output goes negative
825 2371 : if (EnergyFactorAdjFactor <= 0.0) {
826 0 : if (state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).EnergyFactorCurveErrorCount < 1) {
827 0 : ++state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).EnergyFactorCurveErrorCount;
828 0 : ShowWarningError(state,
829 0 : format("{} \"{}\":",
830 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).UnitType,
831 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).Name));
832 0 : ShowContinueError(state, format(" Energy Factor Curve output is <= 0.0 ({:.5T}).", EnergyFactorAdjFactor));
833 0 : ShowContinueError(
834 : state,
835 0 : format(
836 : " Negative value occurs using an inlet air dry-bulb temperature of {:.2T} and an inlet air relative humidity of {:.1T}.",
837 : InletAirTemp,
838 : InletAirRH));
839 0 : ShowContinueErrorTimeStamp(state, " Dehumidifier turned off for this time step but simulation continues.");
840 : } else {
841 0 : ShowRecurringWarningErrorAtEnd(state,
842 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).UnitType + " \"" +
843 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).Name +
844 : "\": Energy Factor Curve output is <= 0.0 warning continues...",
845 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).EnergyFactorCurveErrorIndex,
846 : EnergyFactorAdjFactor,
847 : EnergyFactorAdjFactor);
848 : }
849 0 : ElectricPowerAvg = 0.0;
850 0 : PLR = 0.0;
851 0 : RunTimeFraction = 0.0;
852 : } else {
853 : // EnergyFactorAdjFactor is not negative, so proceed with calculations
854 2371 : EnergyFactor = EnergyFactorAdjFactor * state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).RatedEnergyFactor;
855 :
856 2371 : if (state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).PartLoadCurveIndex > 0) {
857 2371 : PLF = CurveValue(
858 2371 : state, state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).PartLoadCurveIndex, PLR); // Calculate part load fraction
859 : } else {
860 0 : PLF = 1.0;
861 : }
862 :
863 2371 : if (PLF < 0.7) {
864 0 : if (state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).LowPLFErrorCount < 1) {
865 0 : ++state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).LowPLFErrorCount;
866 0 : ShowWarningError(state,
867 0 : format("{} \"{}\":",
868 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).UnitType,
869 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).Name));
870 0 : ShowContinueError(
871 0 : state, format(" The Part Load Fraction Correlation Curve output is ({:.2T}) at a part-load ratio ={:.3T}", PLF, PLR));
872 0 : ShowContinueErrorTimeStamp(state,
873 : " PLF curve values must be >= 0.7. PLF has been reset to 0.7 and simulation is continuing.");
874 : } else {
875 0 : ShowRecurringWarningErrorAtEnd(state,
876 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).UnitType + " \"" +
877 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).Name +
878 : "\": Part Load Fraction Correlation Curve output < 0.7 warning continues...",
879 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).LowPLFErrorIndex,
880 : PLF,
881 : PLF);
882 : }
883 0 : PLF = 0.7;
884 : }
885 :
886 2371 : if (PLF > 1.0) {
887 0 : if (state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).HighPLFErrorCount < 1) {
888 0 : ++state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).HighPLFErrorCount;
889 0 : ShowWarningError(state,
890 0 : format("{} \"{}\":",
891 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).UnitType,
892 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).Name));
893 0 : ShowContinueError(
894 0 : state, format(" The Part Load Fraction Correlation Curve output is ({:.2T}) at a part-load ratio ={:.3T}", PLF, PLR));
895 0 : ShowContinueErrorTimeStamp(state,
896 : " PLF curve values must be < 1.0. PLF has been reset to 1.0 and simulation is continuing.");
897 : } else {
898 0 : ShowRecurringWarningErrorAtEnd(state,
899 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).UnitType + " \"" +
900 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).Name +
901 : "\": Part Load Fraction Correlation Curve output > 1.0 warning continues...",
902 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).HighPLFErrorIndex,
903 : PLF,
904 : PLF);
905 : }
906 0 : PLF = 1.0;
907 : }
908 :
909 2371 : if (PLF > 0.0 && PLF >= PLR) {
910 2371 : RunTimeFraction = PLR / PLF; // Calculate dehumidifier runtime fraction
911 : } else {
912 0 : if (state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).PLFPLRErrorCount < 1) {
913 0 : ++state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).PLFPLRErrorCount;
914 0 : ShowWarningError(state,
915 0 : format("{} \"{}\":",
916 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).UnitType,
917 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).Name));
918 0 : ShowContinueError(
919 : state,
920 0 : format("The part load fraction was less than the part load ratio calculated for this time step [PLR={:.4T}, PLF={:.4T}].",
921 : PLR,
922 : PLF));
923 0 : ShowContinueError(state, "Runtime fraction reset to 1 and the simulation will continue.");
924 0 : ShowContinueErrorTimeStamp(state, "");
925 : } else {
926 0 : ShowRecurringWarningErrorAtEnd(state,
927 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).UnitType + " \"" +
928 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).Name +
929 : "\": Part load fraction less than part load ratio warning continues...",
930 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).PLFPLRErrorIndex);
931 : }
932 0 : RunTimeFraction = 1.0;
933 : }
934 :
935 2371 : if (RunTimeFraction > 1.0 && std::abs(RunTimeFraction - 1.0) > 0.001) {
936 0 : if (state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).HighRTFErrorCount < 1) {
937 0 : ++state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).HighRTFErrorCount;
938 0 : ShowWarningError(state,
939 0 : format("{} \"{}\":",
940 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).UnitType,
941 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).Name));
942 0 : ShowContinueError(state, format("The runtime fraction for this zone dehumidifier exceeded 1.0 [{:.4T}].", RunTimeFraction));
943 0 : ShowContinueError(state, "Runtime fraction reset to 1 and the simulation will continue.");
944 0 : ShowContinueErrorTimeStamp(state, "");
945 : } else {
946 0 : ShowRecurringWarningErrorAtEnd(state,
947 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).UnitType + " \"" +
948 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).Name +
949 : "\": Runtime fraction for zone dehumidifier exceeded 1.0 warning continues...",
950 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).HighRTFErrorIndex,
951 : RunTimeFraction,
952 : RunTimeFraction);
953 : }
954 0 : RunTimeFraction = 1.0;
955 : }
956 :
957 : // ElectricPowerOnCycle = Water removal volumetric rate (L/day) / (Energy Factor(L/kWh) * 24 hrs/day ) * 1000 Wh/kWh
958 2371 : ElectricPowerOnCycle = WaterRemovalVolRate / (EnergyFactor * 24.0) * 1000.0; // Watts
959 : // ElectricPowerAvg = ElectricPowerOnCycle * RTF + (1-RTF)*OffCycleParsiticLoad
960 2371 : ElectricPowerAvg =
961 2371 : ElectricPowerOnCycle * RunTimeFraction +
962 2371 : (1.0 - RunTimeFraction) * state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).OffCycleParasiticLoad; // average Watts
963 : }
964 :
965 2371 : LatentOutput = WaterRemovalMassRate * PLR; // Average moisture removal rate, kg/s, for this timestep
966 2371 : hfg = PsyHfgAirFnWTdb(InletAirHumRat, InletAirTemp);
967 2371 : SensibleOutput = (LatentOutput * hfg) + ElectricPowerAvg; // Average sensible output, Watts
968 : // Send SensibleOutput to zone air heat balance via SysDepZoneLoads in ZoneEquipmentManager
969 :
970 2371 : state.dataLoopNodes->Node(AirInletNodeNum).MassFlowRate = state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).RatedAirMassFlow * PLR;
971 2371 : AirMassFlowRate = state.dataLoopNodes->Node(AirInletNodeNum).MassFlowRate; // Average air mass flow for this timestep
972 2371 : Cp = PsyCpAirFnW(InletAirHumRat); // Heat capacity of air
973 2371 : if (AirMassFlowRate > 0.0 && Cp > 0.0) {
974 4742 : OutletAirTemp = InletAirTemp + (ElectricPowerOnCycle + (WaterRemovalMassRate * hfg)) /
975 2371 : (state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).RatedAirMassFlow * Cp);
976 2371 : OutletAirHumRat = InletAirHumRat - LatentOutput / AirMassFlowRate;
977 : } else {
978 0 : OutletAirTemp = InletAirTemp;
979 0 : OutletAirHumRat = InletAirHumRat;
980 : }
981 :
982 : } else {
983 :
984 : // No load or not available or inlet air temps beyond min/max limits, then set outlet conditions
985 : // equal to inlet conditions and PLR = RTF = 0.0
986 48618 : OutletAirTemp = InletAirTemp;
987 48618 : OutletAirHumRat = InletAirHumRat;
988 48618 : PLR = 0.0;
989 48618 : RunTimeFraction = 0.0;
990 48618 : state.dataLoopNodes->Node(AirInletNodeNum).MassFlowRate = 0.0;
991 : // If available but didn't operate, then set electric power = off cycle parasitic load.
992 : // Else, electric power = 0.0
993 48618 : if (GetCurrentScheduleValue(state, state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).SchedPtr) > 0.0) {
994 48618 : ElectricPowerAvg =
995 48618 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).OffCycleParasiticLoad; // off cycle parasitic is on entire timestep
996 : } else {
997 0 : ElectricPowerAvg = 0.0;
998 : }
999 : }
1000 :
1001 50989 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).OutletAirTemp =
1002 : OutletAirTemp; // Update report variable here. Node outlet Temp set equal
1003 : // to Node inlet Temp in Update subroutine
1004 50989 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).OutletAirHumRat =
1005 : OutletAirHumRat; // Store in structure, updated outlet node in Update subroutine
1006 :
1007 : // Use inlet air temperature in outlet air enthalpy calculation... since the sensible heat output
1008 : // from the dehumidifier is being sent directly to the zone air heat balance for next hvac simulation time step
1009 50989 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).OutletAirEnthalpy = PsyHFnTdbW(InletAirTemp, OutletAirHumRat);
1010 :
1011 50989 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).SensHeatingRate =
1012 50989 : SensibleOutput; // Report variable update, W, avg sens output when unit is 'on'
1013 50989 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).WaterRemovalRate = LatentOutput; // Report variable update, kg/s
1014 50989 : LatentOutput = -LatentOutput; // change sign... negative is dehumidification in zone air balance
1015 :
1016 50989 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).OffCycleParasiticElecPower =
1017 50989 : (1.0 - RunTimeFraction) * state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).OffCycleParasiticLoad;
1018 50989 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).ElecPower = ElectricPowerAvg;
1019 50989 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).DehumidPLR = PLR;
1020 50989 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).DehumidRTF = RunTimeFraction;
1021 50989 : }
1022 :
1023 50989 : void UpdateZoneDehumidifier(EnergyPlusData &state, int const ZoneDehumNum) // Number of the current zone dehumidifier being simulated
1024 : {
1025 :
1026 : // SUBROUTINE INFORMATION:
1027 : // AUTHOR Don Shirey, FSEC
1028 : // DATE WRITTEN August 2009
1029 : // MODIFIED na
1030 : // RE-ENGINEERED na
1031 :
1032 : // PURPOSE OF THIS SUBROUTINE:
1033 : // This subroutine is for passing results to the outlet air node.
1034 :
1035 : // METHODOLOGY EMPLOYED:
1036 : // na
1037 :
1038 : // REFERENCES:
1039 : // na
1040 :
1041 : // Using/Aliasing
1042 : // Locals
1043 : // SUBROUTINE ARGUMENT DEFINITIONS:
1044 :
1045 : // SUBROUTINE PARAMETER DEFINITIONS:
1046 : // na
1047 :
1048 : // INTERFACE BLOCK SPECIFICATIONS:
1049 : // na
1050 :
1051 : // DERIVED TYPE DEFINITIONS:
1052 : // na
1053 :
1054 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1055 : int AirInletNodeNum; // Node number corresponding to the air entering dehumidifier
1056 : int AirOutletNodeNum; // Node number corresponding to the air leaving dehumidifier
1057 :
1058 50989 : AirInletNodeNum = state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).AirInletNodeNum;
1059 50989 : AirOutletNodeNum = state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).AirOutletNodeNum;
1060 :
1061 : // Changed outlet node properties
1062 50989 : state.dataLoopNodes->Node(AirOutletNodeNum).Enthalpy = state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).OutletAirEnthalpy;
1063 50989 : state.dataLoopNodes->Node(AirOutletNodeNum).HumRat = state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).OutletAirHumRat;
1064 : // Set outlet temp = inlet temp; send excess sensible heat directly to air heat balance
1065 : // (via SensibleOutput and QSensOut) for the next hvac simulation time step.
1066 50989 : state.dataLoopNodes->Node(AirOutletNodeNum).Temp = state.dataLoopNodes->Node(AirInletNodeNum).Temp;
1067 :
1068 : // Pass through output node properties
1069 50989 : state.dataLoopNodes->Node(AirOutletNodeNum).Quality = state.dataLoopNodes->Node(AirInletNodeNum).Quality;
1070 50989 : state.dataLoopNodes->Node(AirOutletNodeNum).Press = state.dataLoopNodes->Node(AirInletNodeNum).Press;
1071 50989 : state.dataLoopNodes->Node(AirOutletNodeNum).MassFlowRate = state.dataLoopNodes->Node(AirInletNodeNum).MassFlowRate;
1072 50989 : state.dataLoopNodes->Node(AirOutletNodeNum).MassFlowRateMin = state.dataLoopNodes->Node(AirInletNodeNum).MassFlowRateMin;
1073 50989 : state.dataLoopNodes->Node(AirOutletNodeNum).MassFlowRateMax = state.dataLoopNodes->Node(AirInletNodeNum).MassFlowRateMax;
1074 50989 : state.dataLoopNodes->Node(AirOutletNodeNum).MassFlowRateMinAvail = state.dataLoopNodes->Node(AirInletNodeNum).MassFlowRateMinAvail;
1075 50989 : state.dataLoopNodes->Node(AirOutletNodeNum).MassFlowRateMaxAvail = state.dataLoopNodes->Node(AirInletNodeNum).MassFlowRateMaxAvail;
1076 :
1077 50989 : if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
1078 0 : state.dataLoopNodes->Node(AirOutletNodeNum).CO2 = state.dataLoopNodes->Node(AirInletNodeNum).CO2;
1079 : }
1080 50989 : if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
1081 0 : state.dataLoopNodes->Node(AirOutletNodeNum).GenContam = state.dataLoopNodes->Node(AirInletNodeNum).GenContam;
1082 : }
1083 50989 : }
1084 :
1085 50989 : void ReportZoneDehumidifier(EnergyPlusData &state, int const DehumidNum) // Index of the current zone dehumidifier being simulated
1086 : {
1087 :
1088 : // SUBROUTINE INFORMATION:
1089 : // AUTHOR Don Shirey, FSEC
1090 : // DATE WRITTEN August 2009
1091 : // MODIFIED na
1092 : // RE-ENGINEERED na
1093 :
1094 : // PURPOSE OF THIS SUBROUTINE:
1095 : // Fills some of the report variables for the zone dehumidifiers
1096 :
1097 : // Using/Aliasing
1098 50989 : Real64 TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
1099 : using Psychrometrics::RhoH2O;
1100 :
1101 : // DERIVED TYPE DEFINITIONS:
1102 : // na
1103 :
1104 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1105 : Real64 RhoWater; // Density of condensate (water) being removed (kg/m3)
1106 : Real64 InletAirTemp; // Dry-bulb temperature of air entering the dehumidifier (C)
1107 : Real64 OutletAirTemp; // Dry-bulb temperature of air leaving the dehumidifier (C)
1108 : int AirInletNodeNum; // Node number corresponding to the air entering dehumidifier
1109 :
1110 50989 : state.dataZoneDehumidifier->ZoneDehumid(DehumidNum).SensHeatingEnergy =
1111 50989 : state.dataZoneDehumidifier->ZoneDehumid(DehumidNum).SensHeatingRate * TimeStepSysSec;
1112 50989 : state.dataZoneDehumidifier->ZoneDehumid(DehumidNum).WaterRemoved =
1113 50989 : state.dataZoneDehumidifier->ZoneDehumid(DehumidNum).WaterRemovalRate * TimeStepSysSec;
1114 50989 : state.dataZoneDehumidifier->ZoneDehumid(DehumidNum).ElecConsumption =
1115 50989 : state.dataZoneDehumidifier->ZoneDehumid(DehumidNum).ElecPower * TimeStepSysSec;
1116 50989 : state.dataZoneDehumidifier->ZoneDehumid(DehumidNum).OffCycleParasiticElecCons =
1117 50989 : state.dataZoneDehumidifier->ZoneDehumid(DehumidNum).OffCycleParasiticElecPower * TimeStepSysSec;
1118 :
1119 : // Dehumidifier water collection to water storage tank (if needed)
1120 50989 : if (state.dataZoneDehumidifier->ZoneDehumid(DehumidNum).CondensateCollectMode == CondensateOutlet::ToTank) {
1121 : // Calculate and report condensation rate (how much water extracted from the air stream)
1122 : // Volumetric flow of water in m3/s for water system interactions
1123 :
1124 0 : AirInletNodeNum = state.dataZoneDehumidifier->ZoneDehumid(DehumidNum).AirInletNodeNum;
1125 0 : InletAirTemp = state.dataLoopNodes->Node(AirInletNodeNum).Temp;
1126 0 : OutletAirTemp = max((InletAirTemp - 11.0), 1.0); // Assume coil outlet air is 11C (20F) lower than inlet air temp
1127 0 : RhoWater = RhoH2O(OutletAirTemp); // Density of water, minimum temp = 1.0 C
1128 :
1129 0 : if (RhoWater > 0.0) {
1130 0 : state.dataZoneDehumidifier->ZoneDehumid(DehumidNum).DehumidCondVolFlowRate =
1131 0 : state.dataZoneDehumidifier->ZoneDehumid(DehumidNum).WaterRemovalRate / RhoWater;
1132 : }
1133 :
1134 0 : state.dataZoneDehumidifier->ZoneDehumid(DehumidNum).DehumidCondVol =
1135 0 : state.dataZoneDehumidifier->ZoneDehumid(DehumidNum).DehumidCondVolFlowRate * TimeStepSysSec;
1136 :
1137 0 : state.dataWaterData->WaterStorage(state.dataZoneDehumidifier->ZoneDehumid(DehumidNum).CondensateTankID)
1138 0 : .VdotAvailSupply(state.dataZoneDehumidifier->ZoneDehumid(DehumidNum).CondensateTankSupplyARRID) =
1139 0 : state.dataZoneDehumidifier->ZoneDehumid(DehumidNum).DehumidCondVolFlowRate;
1140 : // Assume water outlet temp = air outlet temp.... same assumption in other places in code (e.g., water coil component)
1141 0 : state.dataWaterData->WaterStorage(state.dataZoneDehumidifier->ZoneDehumid(DehumidNum).CondensateTankID)
1142 0 : .TwaterSupply(state.dataZoneDehumidifier->ZoneDehumid(DehumidNum).CondensateTankSupplyARRID) = OutletAirTemp;
1143 : }
1144 50989 : }
1145 :
1146 79 : bool GetZoneDehumidifierNodeNumber(EnergyPlusData &state, int const NodeNumber) // Node being tested
1147 : {
1148 :
1149 : // FUNCTION INFORMATION:
1150 : // AUTHOR Lixing Gu
1151 : // DATE WRITTEN August 2009
1152 : // MODIFIED na
1153 : // RE-ENGINEERED na
1154 :
1155 : // PURPOSE OF THIS FUNCTION:
1156 : // After making sure get input is done, the node number of indicated
1157 : // zone dehumidifier is returned.
1158 :
1159 : // Return value
1160 : bool FindZoneDehumidifierNodeNumber; // Zone Dehumidifier Node Number Check
1161 :
1162 79 : if (state.dataZoneDehumidifier->GetInputFlag) {
1163 22 : GetZoneDehumidifierInput(state);
1164 22 : state.dataZoneDehumidifier->GetInputFlag = false;
1165 : }
1166 :
1167 79 : FindZoneDehumidifierNodeNumber = false;
1168 86 : for (int ZoneDehumidIndex = 1; ZoneDehumidIndex <= (int)state.dataZoneDehumidifier->ZoneDehumid.size(); ++ZoneDehumidIndex) {
1169 9 : if (NodeNumber == state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).AirInletNodeNum) {
1170 1 : FindZoneDehumidifierNodeNumber = true;
1171 1 : break;
1172 : }
1173 8 : if (NodeNumber == state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).AirOutletNodeNum) {
1174 1 : FindZoneDehumidifierNodeNumber = true;
1175 1 : break;
1176 : }
1177 : }
1178 :
1179 79 : return FindZoneDehumidifierNodeNumber;
1180 : }
1181 :
1182 0 : int getZoneDehumidifierIndex(EnergyPlusData &state, std::string_view CompName)
1183 : {
1184 0 : if (state.dataZoneDehumidifier->GetInputFlag) {
1185 0 : GetZoneDehumidifierInput(state);
1186 0 : state.dataZoneDehumidifier->GetInputFlag = false;
1187 : }
1188 :
1189 0 : for (int ZoneDehumidNum = 1; ZoneDehumidNum <= (int)state.dataZoneDehumidifier->ZoneDehumid.size(); ++ZoneDehumidNum) {
1190 0 : if (Util::SameString(state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidNum).Name, CompName)) {
1191 0 : return ZoneDehumidNum;
1192 : }
1193 : }
1194 :
1195 0 : return 0;
1196 : }
1197 :
1198 : } // namespace ZoneDehumidifier
1199 :
1200 : } // namespace EnergyPlus
|