Line data Source code
1 : // EnergyPlus, Copyright (c) 1996-2023, The Board of Trustees of the University of Illinois,
2 : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
3 : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
4 : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
5 : // contributors. All rights reserved.
6 : //
7 : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
8 : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
9 : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
10 : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
11 : // derivative works, and perform publicly and display publicly, and to permit others to do so.
12 : //
13 : // Redistribution and use in source and binary forms, with or without modification, are permitted
14 : // provided that the following conditions are met:
15 : //
16 : // (1) Redistributions of source code must retain the above copyright notice, this list of
17 : // conditions and the following disclaimer.
18 : //
19 : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
20 : // conditions and the following disclaimer in the documentation and/or other materials
21 : // provided with the distribution.
22 : //
23 : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
24 : // the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
25 : // used to endorse or promote products derived from this software without specific prior
26 : // written permission.
27 : //
28 : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
29 : // without changes from the version obtained under this License, or (ii) Licensee makes a
30 : // reference solely to the software portion of its product, Licensee must refer to the
31 : // software as "EnergyPlus version X" software, where "X" is the version number Licensee
32 : // obtained under this License and may not use a different name for the software. Except as
33 : // specifically required in this Section (4), Licensee shall not use in a company name, a
34 : // product name, in advertising, publicity, or other promotional activities any name, trade
35 : // name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
36 : // similar designation, without the U.S. Department of Energy's prior written consent.
37 : //
38 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
39 : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
40 : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
41 : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
43 : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
45 : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46 : // POSSIBILITY OF SUCH DAMAGE.
47 :
48 : // C++ Headers
49 : #include <cmath>
50 :
51 : // ObjexxFCL Headers
52 : #include <ObjexxFCL/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 112664 : 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 112664 : if (state.dataZoneDehumidifier->GetInputFlag) {
141 2 : GetZoneDehumidifierInput(state);
142 2 : state.dataZoneDehumidifier->GetInputFlag = false;
143 : }
144 :
145 : // Find the correct zone dehumidifier
146 112664 : if (CompIndex == 0) {
147 2 : ZoneDehumidNum = UtilityRoutines::FindItemInList(CompName, state.dataZoneDehumidifier->ZoneDehumid);
148 2 : if (ZoneDehumidNum == 0) {
149 0 : ShowFatalError(state, "SimZoneDehumidifier: Unit not found= " + CompName);
150 : }
151 2 : CompIndex = ZoneDehumidNum;
152 : } else {
153 112662 : ZoneDehumidNum = CompIndex;
154 112662 : int NumDehumidifiers = (int)state.dataZoneDehumidifier->ZoneDehumid.size();
155 112662 : 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 0 : CompName));
161 : }
162 112662 : 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 112664 : QZnDehumidReq = state.dataZoneEnergyDemand->ZoneSysMoistureDemand(ZoneNum).RemainingOutputReqToDehumidSP; // Negative means dehumidify
175 :
176 112664 : InitZoneDehumidifier(state, ZoneDehumidNum);
177 :
178 112664 : CalcZoneDehumidifier(state, ZoneDehumidNum, QZnDehumidReq, QSensOut, QLatOut);
179 :
180 112664 : UpdateZoneDehumidifier(state, ZoneDehumidNum);
181 :
182 112664 : ReportZoneDehumidifier(state, ZoneDehumidNum);
183 112664 : }
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 48 : Array1D_string Alphas; // Alpha input items for object
219 48 : Array1D_string cAlphaFields; // Alpha field names
220 48 : Array1D_string cNumericFields; // Numeric field names
221 48 : Array1D<Real64> Numbers; // Numeric input items for object
222 48 : Array1D_bool lAlphaBlanks; // Logical array, alpha field input BLANK = .TRUE.
223 48 : 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 : UtilityRoutines::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 = DataGlobalConstants::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, cAlphaFields(2) + " not found = " + Alphas(2));
268 0 : ShowContinueError(state,
269 0 : "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 2 : 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 2 : 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, cNumericFields(1) + " must be greater than zero.");
302 0 : ShowContinueError(state, format("Value specified = {:.5T}", Numbers(1)));
303 0 : ShowContinueError(state, "Occurs in " + CurrentModuleObject + " = " + state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name);
304 0 : ErrorsFound = true;
305 : }
306 :
307 : // N2, \field Rated Energy Factor
308 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).RatedEnergyFactor = Numbers(2);
309 2 : if (state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).RatedEnergyFactor <= 0.0) {
310 0 : ShowSevereError(state, cNumericFields(2) + " must be greater than zero.");
311 0 : ShowContinueError(state, format("Value specified = {:.5T}", Numbers(2)));
312 0 : ShowContinueError(state, "Occurs in " + CurrentModuleObject + " = " + state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name);
313 0 : ErrorsFound = true;
314 : }
315 :
316 : // N3, \field Rated Air Flow Rate
317 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).RatedAirVolFlow = Numbers(3);
318 2 : if (state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).RatedAirVolFlow <= 0.0) {
319 0 : ShowSevereError(state, cNumericFields(3) + " must be greater than zero.");
320 0 : ShowContinueError(state, format("Value specified = {:.5T}", Numbers(3)));
321 0 : ShowContinueError(state, "Occurs in " + CurrentModuleObject + " = " + state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name);
322 0 : ErrorsFound = true;
323 : }
324 :
325 : // A5, \field Water Removal Curve Name
326 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).WaterRemovalCurveIndex =
327 2 : GetCurveIndex(state, Alphas(5)); // Convert curve name to index number
328 2 : if (state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).WaterRemovalCurveIndex == 0) {
329 0 : if (lAlphaBlanks(5)) {
330 0 : ShowSevereError(state,
331 0 : std::string{RoutineName} + ':' + CurrentModuleObject + "=\"" + cAlphaFields(5) + "\" is required, missing for " +
332 0 : cAlphaFields(1) + " = " + state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name);
333 : } else {
334 0 : ShowSevereError(state, cAlphaFields(5) + " not found = " + Alphas(5));
335 0 : ShowContinueError(state,
336 0 : "Occurs in " + CurrentModuleObject + " = " + state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name);
337 : }
338 0 : ErrorsFound = true;
339 : } else {
340 : // Verify Curve object, only legal type is BiQuadratic
341 6 : ErrorsFound |= Curve::CheckCurveDims(state,
342 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).WaterRemovalCurveIndex, // Curve index
343 : {2}, // Valid dimensions
344 : RoutineName, // Routine name
345 : CurrentModuleObject, // Object Type
346 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name, // Object Name
347 2 : cAlphaFields(5)); // Field Name
348 :
349 2 : if (!ErrorsFound) {
350 4 : CurveVal = CurveValue(
351 2 : state, state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).WaterRemovalCurveIndex, RatedInletAirTemp, RatedInletAirRH);
352 2 : if (CurveVal > 1.10 || CurveVal < 0.90) {
353 0 : ShowWarningError(state, cAlphaFields(5) + " output is not equal to 1.0");
354 0 : ShowContinueError(state, "(+ or -10%) at rated conditions for " + CurrentModuleObject + " = " + Alphas(1));
355 0 : ShowContinueError(state, format("Curve output at rated conditions = {:.3T}", CurveVal));
356 : }
357 : }
358 : }
359 :
360 : // A6, \field Energy Factor Curve Name
361 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).EnergyFactorCurveIndex =
362 2 : GetCurveIndex(state, Alphas(6)); // convert curve name to number
363 2 : if (state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).EnergyFactorCurveIndex == 0) {
364 0 : if (lAlphaBlanks(6)) {
365 0 : ShowSevereError(state,
366 0 : std::string{RoutineName} + ':' + CurrentModuleObject + "=\"" + cAlphaFields(6) + "\" is required, missing for " +
367 0 : cAlphaFields(1) + " = " + state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name);
368 : } else {
369 0 : ShowSevereError(state, cAlphaFields(6) + " not found = " + Alphas(6));
370 0 : ShowContinueError(state,
371 0 : "Occurs in " + CurrentModuleObject + " = " + state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name);
372 : }
373 0 : ErrorsFound = true;
374 : } else {
375 : // Verify Curve Object, only legal type is BiQuadratic
376 6 : ErrorsFound |= Curve::CheckCurveDims(state,
377 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).EnergyFactorCurveIndex, // Curve index
378 : {2}, // Valid dimensions
379 : RoutineName, // Routine name
380 : CurrentModuleObject, // Object Type
381 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name, // Object Name
382 2 : cAlphaFields(6)); // Field Name
383 :
384 2 : if (!ErrorsFound) {
385 4 : CurveVal = CurveValue(
386 2 : state, state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).EnergyFactorCurveIndex, RatedInletAirTemp, RatedInletAirRH);
387 2 : if (CurveVal > 1.10 || CurveVal < 0.90) {
388 0 : ShowWarningError(state, cAlphaFields(6) + " output is not equal to 1.0");
389 0 : ShowContinueError(state, "(+ or -10%) at rated conditions for " + CurrentModuleObject + " = " + Alphas(1));
390 0 : ShowContinueError(state, format("Curve output at rated conditions = {:.3T}", CurveVal));
391 : }
392 : }
393 : }
394 :
395 : // A7, \field Part Load Fraction Correlation Curve Name
396 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).PartLoadCurveIndex =
397 2 : GetCurveIndex(state, Alphas(7)); // convert curve name to number
398 2 : if (state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).PartLoadCurveIndex == 0) {
399 0 : if (lAlphaBlanks(7)) {
400 0 : ShowSevereError(state,
401 0 : std::string{RoutineName} + ':' + CurrentModuleObject + "=\"" + cAlphaFields(7) + "\" is required, missing for " +
402 0 : cAlphaFields(1) + " = " + state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name);
403 : } else {
404 0 : ShowSevereError(state, cAlphaFields(7) + " not found = " + Alphas(7));
405 0 : ShowContinueError(state,
406 0 : "Occurs in " + CurrentModuleObject + " = " + state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name);
407 : }
408 0 : ErrorsFound = true;
409 : } else {
410 : // Verify Curve Object, legal types are Quadratic and Cubic
411 6 : ErrorsFound |= Curve::CheckCurveDims(state,
412 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).PartLoadCurveIndex, // Curve index
413 : {1}, // Valid dimensions
414 : RoutineName, // Routine name
415 : CurrentModuleObject, // Object Type
416 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name, // Object Name
417 2 : cAlphaFields(7)); // Field Name
418 : }
419 :
420 : // N4, \field Minimum Dry-Bulb Temperature for Dehumidifier Operation
421 : // N5, \field Maximum Dry-Bulb Temperature for Dehumidifier Operation
422 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).MinInletAirTemp = Numbers(4);
423 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).MaxInletAirTemp = Numbers(5);
424 :
425 4 : if (state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).MinInletAirTemp >=
426 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).MaxInletAirTemp) {
427 0 : ShowSevereError(state, cNumericFields(5) + " must be greater than " + cNumericFields(4));
428 0 : ShowContinueError(state, format("{} specified = {:.1T}", cNumericFields(5), Numbers(5)));
429 0 : ShowContinueError(state, format("{} specified = {:.1T}", cNumericFields(4), Numbers(4)));
430 0 : ShowContinueError(state, "Occurs in " + CurrentModuleObject + " = " + state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name);
431 0 : ErrorsFound = true;
432 : }
433 :
434 : // N6, \field Off Cycle Parasitic Electric Load
435 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).OffCycleParasiticLoad = Numbers(6); // Off Cycle Parasitic Load [W]
436 :
437 2 : if (state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).OffCycleParasiticLoad < 0.0) {
438 0 : ShowSevereError(state, cNumericFields(6) + " must be >= zero.");
439 0 : ShowContinueError(state, format("Value specified = {:.2T}", Numbers(6)));
440 0 : ShowContinueError(state, "Occurs in " + CurrentModuleObject + " = " + state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name);
441 0 : ErrorsFound = true;
442 : }
443 :
444 : // A8; \field Condensate Collection Water Storage Tank Name
445 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).CondensateCollectName = Alphas(8);
446 2 : if (lAlphaBlanks(8)) {
447 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).CondensateCollectMode = CondensateOutlet::Discarded;
448 : } else {
449 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).CondensateCollectMode = CondensateOutlet::ToTank;
450 0 : SetupTankSupplyComponent(state,
451 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name,
452 : CurrentModuleObject,
453 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).CondensateCollectName,
454 : ErrorsFound,
455 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).CondensateTankID,
456 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).CondensateTankSupplyARRID);
457 : }
458 :
459 : } // DO ZoneDehumidIndex=1,NumDehumidifiers
460 :
461 24 : Alphas.deallocate();
462 24 : cAlphaFields.deallocate();
463 24 : cNumericFields.deallocate();
464 24 : Numbers.deallocate();
465 24 : lAlphaBlanks.deallocate();
466 24 : lNumericBlanks.deallocate();
467 :
468 24 : if (ErrorsFound) {
469 0 : ShowFatalError(state, std::string{RoutineName} + ':' + CurrentModuleObject + ": Errors found in input.");
470 : }
471 :
472 26 : for (ZoneDehumidIndex = 1; ZoneDehumidIndex <= NumDehumidifiers; ++ZoneDehumidIndex) {
473 : // Set up report variables for the dehumidifiers
474 8 : SetupOutputVariable(state,
475 : "Zone Dehumidifier Sensible Heating Rate",
476 : OutputProcessor::Unit::W,
477 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).SensHeatingRate,
478 : OutputProcessor::SOVTimeStepType::System,
479 : OutputProcessor::SOVStoreType::Average,
480 4 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name);
481 8 : SetupOutputVariable(state,
482 : "Zone Dehumidifier Sensible Heating Energy",
483 : OutputProcessor::Unit::J,
484 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).SensHeatingEnergy,
485 : OutputProcessor::SOVTimeStepType::System,
486 : OutputProcessor::SOVStoreType::Summed,
487 4 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name);
488 8 : SetupOutputVariable(state,
489 : "Zone Dehumidifier Removed Water Mass Flow Rate",
490 : OutputProcessor::Unit::kg_s,
491 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).WaterRemovalRate,
492 : OutputProcessor::SOVTimeStepType::System,
493 : OutputProcessor::SOVStoreType::Average,
494 4 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name);
495 8 : SetupOutputVariable(state,
496 : "Zone Dehumidifier Removed Water Mass",
497 : OutputProcessor::Unit::kg,
498 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).WaterRemoved,
499 : OutputProcessor::SOVTimeStepType::System,
500 : OutputProcessor::SOVStoreType::Summed,
501 4 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name);
502 8 : SetupOutputVariable(state,
503 : "Zone Dehumidifier Electricity Rate",
504 : OutputProcessor::Unit::W,
505 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).ElecPower,
506 : OutputProcessor::SOVTimeStepType::System,
507 : OutputProcessor::SOVStoreType::Average,
508 4 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name);
509 8 : SetupOutputVariable(state,
510 : "Zone Dehumidifier Electricity Energy",
511 : OutputProcessor::Unit::J,
512 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).ElecConsumption,
513 : OutputProcessor::SOVTimeStepType::System,
514 : OutputProcessor::SOVStoreType::Summed,
515 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name,
516 : _,
517 : "Electricity",
518 : "COOLING",
519 : _,
520 2 : "System");
521 8 : SetupOutputVariable(state,
522 : "Zone Dehumidifier Off Cycle Parasitic Electricity Rate",
523 : OutputProcessor::Unit::W,
524 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).OffCycleParasiticElecPower,
525 : OutputProcessor::SOVTimeStepType::System,
526 : OutputProcessor::SOVStoreType::Average,
527 4 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name);
528 8 : SetupOutputVariable(state,
529 : "Zone Dehumidifier Off Cycle Parasitic Electricity Energy",
530 : OutputProcessor::Unit::J,
531 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).OffCycleParasiticElecCons,
532 : OutputProcessor::SOVTimeStepType::System,
533 : OutputProcessor::SOVStoreType::Summed,
534 4 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name);
535 8 : SetupOutputVariable(state,
536 : "Zone Dehumidifier Part Load Ratio",
537 : OutputProcessor::Unit::None,
538 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).DehumidPLR,
539 : OutputProcessor::SOVTimeStepType::System,
540 : OutputProcessor::SOVStoreType::Average,
541 4 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name);
542 8 : SetupOutputVariable(state,
543 : "Zone Dehumidifier Runtime Fraction",
544 : OutputProcessor::Unit::None,
545 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).DehumidRTF,
546 : OutputProcessor::SOVTimeStepType::System,
547 : OutputProcessor::SOVStoreType::Average,
548 4 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name);
549 8 : SetupOutputVariable(state,
550 : "Zone Dehumidifier Outlet Air Temperature",
551 : OutputProcessor::Unit::C,
552 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).OutletAirTemp,
553 : OutputProcessor::SOVTimeStepType::System,
554 : OutputProcessor::SOVStoreType::Average,
555 4 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name);
556 :
557 2 : if (state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).CondensateCollectMode == CondensateOutlet::ToTank) {
558 0 : SetupOutputVariable(state,
559 : "Zone Dehumidifier Condensate Volume Flow Rate",
560 : OutputProcessor::Unit::m3_s,
561 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).DehumidCondVolFlowRate,
562 : OutputProcessor::SOVTimeStepType::System,
563 : OutputProcessor::SOVStoreType::Average,
564 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name);
565 0 : SetupOutputVariable(state,
566 : "Zone Dehumidifier Condensate Volume",
567 : OutputProcessor::Unit::m3,
568 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).DehumidCondVol,
569 : OutputProcessor::SOVTimeStepType::System,
570 : OutputProcessor::SOVStoreType::Summed,
571 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).Name,
572 : _,
573 : "OnSiteWater",
574 : "Condensate",
575 : _,
576 0 : "System");
577 : }
578 : }
579 24 : }
580 :
581 112664 : void InitZoneDehumidifier(EnergyPlusData &state, int const ZoneDehumNum) // Number of the current zone dehumidifier being simulated
582 : {
583 :
584 : // SUBROUTINE INFORMATION:
585 : // AUTHOR Don Shirey, FSEC
586 : // DATE WRITTEN July/Aug 2009
587 : // MODIFIED na
588 : // RE-ENGINEERED na
589 :
590 : // PURPOSE OF THIS SUBROUTINE:
591 : // This subroutine initializes information for the zone dehumidifier model
592 :
593 : // METHODOLOGY EMPLOYED:
594 : // Use status flags to trigger various initializations
595 :
596 : // Using/Aliasing
597 : using DataZoneEquipment::CheckZoneEquipmentList;
598 : using Psychrometrics::PsyRhoAirFnPbTdbW;
599 : using Psychrometrics::PsyWFnTdbRhPb;
600 :
601 : // SUBROUTINE PARAMETER DEFINITIONS:
602 : static constexpr std::string_view RoutineName("InitZoneDehumidifier");
603 :
604 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
605 : int AirInletNode; // Inlet air node number
606 : Real64 RatedAirHumrat; // Humidity ratio (kg/kg) at rated inlet air conditions of 26.6667C, 60% RH
607 : Real64 RatedAirDBTemp; // Dry-bulb air temperature at rated conditions 26.6667C
608 : Real64 RatedAirRH; // Relative humidity of air (0.6 --> 60%) at rated conditions
609 :
610 : // Need to check all dehumidifiers to see if they are on Zone Equipment List or issue warning
611 112664 : if (!state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).ZoneEquipmentListChecked && state.dataZoneEquip->ZoneEquipInputsFilled) {
612 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).ZoneEquipmentListChecked = true;
613 6 : if (!CheckZoneEquipmentList(state,
614 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).UnitType,
615 2 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).Name)) {
616 0 : ShowSevereError(state,
617 0 : "InitZoneDehumidifier: Zone Dehumidifier=\"" + state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).UnitType + ',' +
618 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).Name +
619 : "\" is not on any ZoneHVAC:EquipmentList. It will not be simulated.");
620 : }
621 : }
622 :
623 112664 : AirInletNode = state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).AirInletNodeNum;
624 : // Do the Begin Environment initializations
625 112664 : if (state.dataGlobal->BeginEnvrnFlag && state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).MyEnvrnFlag) {
626 :
627 : // Set the mass flow rates from the input volume flow rates, at rated conditions of 26.6667C, 60% RH
628 : // Might default back to STP later after discussion with M. Witte, use StdRhoAir instead of calc'd RhoAir at rated conditions
629 11 : RatedAirDBTemp = 26.6667; // 26.6667 C, 80F
630 11 : RatedAirRH = 0.6; // 60% RH
631 11 : RatedAirHumrat = PsyWFnTdbRhPb(state, RatedAirDBTemp, RatedAirRH, state.dataEnvrn->StdBaroPress, RoutineName);
632 11 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).RatedAirMassFlow =
633 22 : PsyRhoAirFnPbTdbW(state, state.dataEnvrn->StdBaroPress, RatedAirDBTemp, RatedAirHumrat, RoutineName) *
634 11 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).RatedAirVolFlow;
635 :
636 : // Set the node max and min mass flow rates on inlet node... outlet node gets updated in UPDATE subroutine
637 11 : state.dataLoopNodes->Node(AirInletNode).MassFlowRateMax = state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).RatedAirMassFlow;
638 11 : state.dataLoopNodes->Node(AirInletNode).MassFlowRateMaxAvail = state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).RatedAirMassFlow;
639 11 : state.dataLoopNodes->Node(AirInletNode).MassFlowRateMinAvail = 0.0;
640 11 : state.dataLoopNodes->Node(AirInletNode).MassFlowRateMin = 0.0;
641 :
642 11 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).MyEnvrnFlag = false;
643 : } // End one time inits
644 :
645 112664 : if (!state.dataGlobal->BeginEnvrnFlag) {
646 112424 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).MyEnvrnFlag = true;
647 : }
648 :
649 : // These initializations are done every iteration
650 112664 : state.dataLoopNodes->Node(AirInletNode).MassFlowRate = state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).RatedAirMassFlow;
651 :
652 : // Zero out the report variables
653 112664 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).SensHeatingRate = 0.0; // Zone Dehumidifier Sensible Heating Rate [W]
654 112664 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).SensHeatingEnergy = 0.0; // Zone Dehumidifier Sensible Heating Energy [J]
655 112664 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).WaterRemovalRate = 0.0; // Zone Dehumidifier Water Removal Rate [kg/s]
656 112664 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).WaterRemoved = 0.0; // Zone Dehumidifier Water Removed [kg]
657 112664 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).ElecPower = 0.0; // Zone Dehumidifier Electric Power [W]
658 112664 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).ElecConsumption = 0.0; // Zone Dehumidifier Electric Consumption [J]
659 112664 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).DehumidPLR = 0.0; // Zone Dehumidifier Part-Load Ratio [-]
660 112664 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).DehumidRTF = 0.0; // Zone Dehumidifier Runtime Fraction [-]
661 112664 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).OffCycleParasiticElecPower =
662 : 0.0; // Zone Dehumidifier Off-Cycle Parasitic Electric Power [W]
663 112664 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).OffCycleParasiticElecCons =
664 : 0.0; // Zone Dehumidifier Off-Cycle Parasitic Electric Consumption [J]
665 112664 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).DehumidCondVolFlowRate =
666 : 0.0; // Zone Dehumidifier Condensate Volumetric Flow Rate [m3/s]
667 112664 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).DehumidCondVol = 0.0; // Zone Dehumidifier Condensate Volume [m3]
668 112664 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).OutletAirTemp =
669 112664 : state.dataLoopNodes->Node(AirInletNode).Temp; // Zone Dehumidifier Outlet Air Temperature [C]
670 112664 : }
671 :
672 112664 : void CalcZoneDehumidifier(EnergyPlusData &state,
673 : int const ZoneDehumNum, // Index number of the current zone dehumidifier being simulated
674 : Real64 const QZnDehumidReq, // Dehumidification load to be met (kg/s), negative value means dehumidification load
675 : Real64 &SensibleOutput, // Sensible (heating) output (W), sent to load predictor for next simulation time step
676 : Real64 &LatentOutput // Latent (dehumidification) output provided (kg/s)
677 : )
678 : {
679 :
680 : // SUBROUTINE INFORMATION:
681 : // AUTHOR Don Shirey, FSEC
682 : // DATE WRITTEN July/Aug 2009
683 : // MODIFIED na
684 : // RE-ENGINEERED na
685 :
686 : // PURPOSE OF THIS SUBROUTINE:
687 : // Calculate the delivered capacity, electric energy consumption and water/condensate
688 : // removal rates for the zone dehumidifier.
689 :
690 : // METHODOLOGY EMPLOYED:
691 : // Cycle the dehumidifier as needed to meet the remaining zone dehumidification load.
692 : // Send excess sensible heat to zone energy balance (via SensibleOutput) for next HVAC time step,
693 : // so set the dehumidifier outlet air temp = inlet air temp to avoid double counting excess sensible.
694 :
695 : // REFERENCES:
696 : // na
697 :
698 : // Using/Aliasing
699 : using Curve::CurveValue;
700 : using Psychrometrics::PsyCpAirFnW;
701 : using Psychrometrics::PsyHfgAirFnWTdb;
702 : using Psychrometrics::PsyHFnTdbW;
703 : using Psychrometrics::PsyRhFnTdbWPb;
704 : using Psychrometrics::RhoH2O;
705 :
706 : // Locals
707 : // SUBROUTINE ARGUMENT DEFINITIONS:
708 :
709 : // SUBROUTINE PARAMETER DEFINITIONS:
710 : static constexpr std::string_view RoutineName("CalcZoneDehumidifier");
711 :
712 : // INTERFACE BLOCK SPECIFICATIONS:
713 : // na
714 :
715 : // DERIVED TYPE DEFINITIONS:
716 : // na
717 :
718 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
719 : Real64 WaterRemovalRateFactor; // Adjustment to Rate Water Removal as a function of inlet air T and RH
720 : Real64 WaterRemovalVolRate; // Actual water removal rate at current inlet air conditions (L/day)
721 : Real64 WaterRemovalMassRate; // Actual water removal rate at current inlet air conditions (kg/s)
722 : Real64 EnergyFactorAdjFactor; // Adjustment to Rate Energy Factor as a function of inlet air T and RH
723 : Real64 EnergyFactor; // Actual Energy Factor as a function of inlet air T and RH
724 : Real64 InletAirTemp; // Dry-bulb temperature of air entering the dehumidifier (C)
725 : Real64 InletAirHumRat; // Humidity ratio of the air entering the dehumidifier (kg/kg)
726 : Real64 InletAirRH; // Relative humidity of air entering the dehumidifier (%)
727 : Real64 OutletAirTemp; // Dry-bulb temperature of air leaving the dehumidifier (C)
728 : Real64 OutletAirHumRat; // Humidity ratio of air leaving the dehumidifier (kg/kg)
729 : Real64 PLR; // Part-load ratio = (dehumid load to be met)/(dehumid capacity of the dehumidifier)
730 : Real64 PLF; // Part-load fraction (-), RuntimeFraction = PLR/PLF
731 : Real64 RunTimeFraction; // Dehumidifier runtime fraction (-)
732 : Real64 ElectricPowerOnCycle; // Electric power when dehumidifier is operating (W)
733 : Real64 ElectricPowerAvg; // Average electric power for this dehumidifier (W)
734 : Real64 hfg; // Enthalpy of evaporation of inlet air (J/kg)
735 : Real64 AirMassFlowRate; // Air mass flow rate through this dehumidifier (kg/s)
736 : Real64 Cp; // Heat capacity of inlet air (J/kg-C)
737 112664 : int AirInletNodeNum(0); // Node number for the inlet air to the dehumidifier
738 112664 : int AirOutletNodeNum(0); // Node number for the outlet air from the dehumidifier
739 :
740 112664 : SensibleOutput = 0.0;
741 112664 : LatentOutput = 0.0;
742 112664 : WaterRemovalRateFactor = 0.0;
743 112664 : AirMassFlowRate = 0.0;
744 112664 : PLR = 0.0;
745 112664 : PLF = 0.0;
746 112664 : EnergyFactorAdjFactor = 0.0;
747 112664 : RunTimeFraction = 0.0;
748 112664 : ElectricPowerAvg = 0.0;
749 112664 : ElectricPowerOnCycle = 0.0;
750 :
751 112664 : AirInletNodeNum = state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).AirInletNodeNum;
752 112664 : AirOutletNodeNum = state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).AirOutletNodeNum;
753 :
754 112664 : InletAirTemp = state.dataLoopNodes->Node(AirInletNodeNum).Temp;
755 112664 : InletAirHumRat = state.dataLoopNodes->Node(AirInletNodeNum).HumRat;
756 112664 : InletAirRH = 100.0 * PsyRhFnTdbWPb(state, InletAirTemp, InletAirHumRat, state.dataEnvrn->OutBaroPress, RoutineName); // RH in percent (%)
757 :
758 118498 : if (QZnDehumidReq < 0.0 && GetCurrentScheduleValue(state, state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).SchedPtr) > 0.0 &&
759 118498 : InletAirTemp >= state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).MinInletAirTemp &&
760 2917 : InletAirTemp <= state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).MaxInletAirTemp) {
761 : // A dehumidification load is being requested and dehumidifier is available (schedule value > 0)
762 : // and the inlet air temperature is within the min/max values specified by user input
763 :
764 2917 : WaterRemovalRateFactor =
765 5834 : CurveValue(state, state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).WaterRemovalCurveIndex, InletAirTemp, InletAirRH);
766 : // Warn user if curve output goes negative
767 2917 : if (WaterRemovalRateFactor <= 0.0) {
768 0 : if (state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).WaterRemovalCurveErrorCount < 1) {
769 0 : ++state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).WaterRemovalCurveErrorCount;
770 0 : ShowWarningError(state,
771 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).UnitType + " \"" +
772 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).Name + "\":");
773 0 : ShowContinueError(state, format(" Water Removal Rate Curve output is <= 0.0 ({:.5T}).", WaterRemovalRateFactor));
774 0 : ShowContinueError(
775 : state,
776 0 : format(
777 : " Negative value occurs using an inlet air dry-bulb temperature of {:.2T} and an inlet air relative humidity of {:.1T}.",
778 : InletAirTemp,
779 0 : InletAirRH));
780 0 : ShowContinueErrorTimeStamp(state, " Dehumidifier turned off for this time step but simulation continues.");
781 : } else {
782 0 : ShowRecurringWarningErrorAtEnd(state,
783 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).UnitType + " \"" +
784 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).Name +
785 : "\": Water Removal Rate Curve output is <= 0.0 warning continues...",
786 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).WaterRemovalCurveErrorIndex,
787 : WaterRemovalRateFactor,
788 : WaterRemovalRateFactor);
789 : }
790 0 : WaterRemovalRateFactor = 0.0;
791 : }
792 :
793 2917 : WaterRemovalVolRate = WaterRemovalRateFactor * state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).RatedWaterRemoval;
794 :
795 2917 : WaterRemovalMassRate =
796 2917 : WaterRemovalVolRate / (24.0 * DataGlobalConstants::SecInHour * 1000.0) *
797 2917 : 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
798 :
799 2917 : if (WaterRemovalMassRate > 0.0) {
800 2917 : PLR = max(0.0, min(1.0, -QZnDehumidReq / WaterRemovalMassRate));
801 : } else {
802 0 : PLR = 0.0;
803 0 : RunTimeFraction = 0.0;
804 : }
805 :
806 2917 : EnergyFactorAdjFactor =
807 5834 : CurveValue(state, state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).EnergyFactorCurveIndex, InletAirTemp, InletAirRH);
808 :
809 : // Warn user if curve output goes negative
810 2917 : if (EnergyFactorAdjFactor <= 0.0) {
811 0 : if (state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).EnergyFactorCurveErrorCount < 1) {
812 0 : ++state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).EnergyFactorCurveErrorCount;
813 0 : ShowWarningError(state,
814 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).UnitType + " \"" +
815 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).Name + "\":");
816 0 : ShowContinueError(state, format(" Energy Factor Curve output is <= 0.0 ({:.5T}).", EnergyFactorAdjFactor));
817 0 : ShowContinueError(
818 : state,
819 0 : format(
820 : " Negative value occurs using an inlet air dry-bulb temperature of {:.2T} and an inlet air relative humidity of {:.1T}.",
821 : InletAirTemp,
822 0 : InletAirRH));
823 0 : ShowContinueErrorTimeStamp(state, " Dehumidifier turned off for this time step but simulation continues.");
824 : } else {
825 0 : ShowRecurringWarningErrorAtEnd(state,
826 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).UnitType + " \"" +
827 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).Name +
828 : "\": Energy Factor Curve output is <= 0.0 warning continues...",
829 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).EnergyFactorCurveErrorIndex,
830 : EnergyFactorAdjFactor,
831 : EnergyFactorAdjFactor);
832 : }
833 0 : ElectricPowerAvg = 0.0;
834 0 : PLR = 0.0;
835 0 : RunTimeFraction = 0.0;
836 : } else {
837 : // EnergyFactorAdjFactor is not negative, so proceed with calculations
838 2917 : EnergyFactor = EnergyFactorAdjFactor * state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).RatedEnergyFactor;
839 :
840 2917 : if (state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).PartLoadCurveIndex > 0) {
841 5834 : PLF = CurveValue(
842 2917 : state, state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).PartLoadCurveIndex, PLR); // Calculate part load fraction
843 : } else {
844 0 : PLF = 1.0;
845 : }
846 :
847 2917 : if (PLF < 0.7) {
848 0 : if (state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).LowPLFErrorCount < 1) {
849 0 : ++state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).LowPLFErrorCount;
850 0 : ShowWarningError(state,
851 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).UnitType + " \"" +
852 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).Name + "\":");
853 0 : ShowContinueError(
854 0 : state, format(" The Part Load Fraction Correlation Curve output is ({:.2T}) at a part-load ratio ={:.3T}", PLF, PLR));
855 0 : ShowContinueErrorTimeStamp(state,
856 : " PLF curve values must be >= 0.7. PLF has been reset to 0.7 and simulation is continuing.");
857 : } else {
858 0 : ShowRecurringWarningErrorAtEnd(state,
859 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).UnitType + " \"" +
860 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).Name +
861 : "\": Part Load Fraction Correlation Curve output < 0.7 warning continues...",
862 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).LowPLFErrorIndex,
863 : PLF,
864 : PLF);
865 : }
866 0 : PLF = 0.7;
867 : }
868 :
869 2917 : if (PLF > 1.0) {
870 0 : if (state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).HighPLFErrorCount < 1) {
871 0 : ++state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).HighPLFErrorCount;
872 0 : ShowWarningError(state,
873 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).UnitType + " \"" +
874 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).Name + "\":");
875 0 : ShowContinueError(
876 0 : state, format(" The Part Load Fraction Correlation Curve output is ({:.2T}) at a part-load ratio ={:.3T}", PLF, PLR));
877 0 : ShowContinueErrorTimeStamp(state,
878 : " PLF curve values must be < 1.0. PLF has been reset to 1.0 and simulation is continuing.");
879 : } else {
880 0 : ShowRecurringWarningErrorAtEnd(state,
881 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).UnitType + " \"" +
882 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).Name +
883 : "\": Part Load Fraction Correlation Curve output > 1.0 warning continues...",
884 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).HighPLFErrorIndex,
885 : PLF,
886 : PLF);
887 : }
888 0 : PLF = 1.0;
889 : }
890 :
891 2917 : if (PLF > 0.0 && PLF >= PLR) {
892 2917 : RunTimeFraction = PLR / PLF; // Calculate dehumidifier runtime fraction
893 : } else {
894 0 : if (state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).PLFPLRErrorCount < 1) {
895 0 : ++state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).PLFPLRErrorCount;
896 0 : ShowWarningError(state,
897 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).UnitType + " \"" +
898 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).Name + "\":");
899 0 : ShowContinueError(
900 : state,
901 0 : format("The part load fraction was less than the part load ratio calculated for this time step [PLR={:.4T}, PLF={:.4T}].",
902 : PLR,
903 0 : PLF));
904 0 : ShowContinueError(state, "Runtime fraction reset to 1 and the simulation will continue.");
905 0 : ShowContinueErrorTimeStamp(state, "");
906 : } else {
907 0 : ShowRecurringWarningErrorAtEnd(state,
908 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).UnitType + " \"" +
909 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).Name +
910 : "\": Part load fraction less than part load ratio warning continues...",
911 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).PLFPLRErrorIndex);
912 : }
913 0 : RunTimeFraction = 1.0;
914 : }
915 :
916 2917 : if (RunTimeFraction > 1.0 && std::abs(RunTimeFraction - 1.0) > 0.001) {
917 0 : if (state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).HighRTFErrorCount < 1) {
918 0 : ++state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).HighRTFErrorCount;
919 0 : ShowWarningError(state,
920 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).UnitType + " \"" +
921 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).Name + "\":");
922 0 : ShowContinueError(state, format("The runtime fraction for this zone dehumidifier exceeded 1.0 [{:.4T}].", RunTimeFraction));
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 : "\": Runtime fraction for zone dehumidifier exceeded 1.0 warning continues...",
930 0 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).HighRTFErrorIndex,
931 : RunTimeFraction,
932 : RunTimeFraction);
933 : }
934 0 : RunTimeFraction = 1.0;
935 : }
936 :
937 : // ElectricPowerOnCycle = Water removal volumetric rate (L/day) / (Energy Factor(L/kWh) * 24 hrs/day ) * 1000 Wh/kWh
938 2917 : ElectricPowerOnCycle = WaterRemovalVolRate / (EnergyFactor * 24.0) * 1000.0; // Watts
939 : // ElectricPowerAvg = ElectricPowerOnCycle * RTF + (1-RTF)*OffCycleParsiticLoad
940 2917 : ElectricPowerAvg =
941 2917 : ElectricPowerOnCycle * RunTimeFraction +
942 2917 : (1.0 - RunTimeFraction) * state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).OffCycleParasiticLoad; // average Watts
943 : }
944 :
945 2917 : LatentOutput = WaterRemovalMassRate * PLR; // Average moisture removal rate, kg/s, for this timestep
946 2917 : hfg = PsyHfgAirFnWTdb(InletAirHumRat, InletAirTemp);
947 2917 : SensibleOutput = (LatentOutput * hfg) + ElectricPowerAvg; // Average sensible output, Watts
948 : // Send SensibleOutput to zone air heat balance via SysDepZoneLoads in ZoneEquipmentManager
949 :
950 2917 : state.dataLoopNodes->Node(AirInletNodeNum).MassFlowRate = state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).RatedAirMassFlow * PLR;
951 2917 : AirMassFlowRate = state.dataLoopNodes->Node(AirInletNodeNum).MassFlowRate; // Average air mass flow for this timestep
952 2917 : Cp = PsyCpAirFnW(InletAirHumRat); // Heat capacity of air
953 2917 : if (AirMassFlowRate > 0.0 && Cp > 0.0) {
954 5834 : OutletAirTemp = InletAirTemp + (ElectricPowerOnCycle + (WaterRemovalMassRate * hfg)) /
955 2917 : (state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).RatedAirMassFlow * Cp);
956 2917 : OutletAirHumRat = InletAirHumRat - LatentOutput / AirMassFlowRate;
957 : } else {
958 0 : OutletAirTemp = InletAirTemp;
959 0 : OutletAirHumRat = InletAirHumRat;
960 : }
961 :
962 : } else {
963 :
964 : // No load or not available or inlet air temps beyond min/max limits, then set outlet conditions
965 : // equal to inlet conditions and PLR = RTF = 0.0
966 109747 : OutletAirTemp = InletAirTemp;
967 109747 : OutletAirHumRat = InletAirHumRat;
968 109747 : PLR = 0.0;
969 109747 : RunTimeFraction = 0.0;
970 109747 : state.dataLoopNodes->Node(AirInletNodeNum).MassFlowRate = 0.0;
971 : // If available but didn't operate, then set electric power = off cycle parasitic load.
972 : // Else, electric power = 0.0
973 109747 : if (GetCurrentScheduleValue(state, state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).SchedPtr) > 0.0) {
974 109747 : ElectricPowerAvg =
975 109747 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).OffCycleParasiticLoad; // off cycle parasitic is on entire timestep
976 : } else {
977 0 : ElectricPowerAvg = 0.0;
978 : }
979 : }
980 :
981 112664 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).OutletAirTemp =
982 : OutletAirTemp; // Update report variable here. Node outlet Temp set equal
983 : // to Node inlet Temp in Update subroutine
984 112664 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).OutletAirHumRat =
985 : OutletAirHumRat; // Store in structure, updated outlet node in Update subroutine
986 :
987 : // Use inlet air temperature in outlet air enthalpy calculation... since the sensible heat output
988 : // from the dehumidifier is being sent directly to the zone air heat balance for next hvac simulation time step
989 112664 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).OutletAirEnthalpy = PsyHFnTdbW(InletAirTemp, OutletAirHumRat);
990 :
991 112664 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).SensHeatingRate =
992 112664 : SensibleOutput; // Report variable update, W, avg sens output when unit is 'on'
993 112664 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).WaterRemovalRate = LatentOutput; // Report variable update, kg/s
994 112664 : LatentOutput = -LatentOutput; // change sign... negative is dehumidification in zone air balance
995 :
996 112664 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).OffCycleParasiticElecPower =
997 112664 : (1.0 - RunTimeFraction) * state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).OffCycleParasiticLoad;
998 112664 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).ElecPower = ElectricPowerAvg;
999 112664 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).DehumidPLR = PLR;
1000 112664 : state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).DehumidRTF = RunTimeFraction;
1001 112664 : }
1002 :
1003 112664 : void UpdateZoneDehumidifier(EnergyPlusData &state, int const ZoneDehumNum) // Number of the current zone dehumidifier being simulated
1004 : {
1005 :
1006 : // SUBROUTINE INFORMATION:
1007 : // AUTHOR Don Shirey, FSEC
1008 : // DATE WRITTEN August 2009
1009 : // MODIFIED na
1010 : // RE-ENGINEERED na
1011 :
1012 : // PURPOSE OF THIS SUBROUTINE:
1013 : // This subroutine is for passing results to the outlet air node.
1014 :
1015 : // METHODOLOGY EMPLOYED:
1016 : // na
1017 :
1018 : // REFERENCES:
1019 : // na
1020 :
1021 : // Using/Aliasing
1022 : // Locals
1023 : // SUBROUTINE ARGUMENT DEFINITIONS:
1024 :
1025 : // SUBROUTINE PARAMETER DEFINITIONS:
1026 : // na
1027 :
1028 : // INTERFACE BLOCK SPECIFICATIONS:
1029 : // na
1030 :
1031 : // DERIVED TYPE DEFINITIONS:
1032 : // na
1033 :
1034 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1035 : int AirInletNodeNum; // Node number corresponding to the air entering dehumidifier
1036 : int AirOutletNodeNum; // Node number corresponding to the air leaving dehumidifier
1037 :
1038 112664 : AirInletNodeNum = state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).AirInletNodeNum;
1039 112664 : AirOutletNodeNum = state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).AirOutletNodeNum;
1040 :
1041 : // Changed outlet node properties
1042 112664 : state.dataLoopNodes->Node(AirOutletNodeNum).Enthalpy = state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).OutletAirEnthalpy;
1043 112664 : state.dataLoopNodes->Node(AirOutletNodeNum).HumRat = state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumNum).OutletAirHumRat;
1044 : // Set outlet temp = inlet temp; send excess sensible heat directly to air heat balance
1045 : // (via SensibleOutput and QSensOut) for the next hvac simulation time step.
1046 112664 : state.dataLoopNodes->Node(AirOutletNodeNum).Temp = state.dataLoopNodes->Node(AirInletNodeNum).Temp;
1047 :
1048 : // Pass through output node properties
1049 112664 : state.dataLoopNodes->Node(AirOutletNodeNum).Quality = state.dataLoopNodes->Node(AirInletNodeNum).Quality;
1050 112664 : state.dataLoopNodes->Node(AirOutletNodeNum).Press = state.dataLoopNodes->Node(AirInletNodeNum).Press;
1051 112664 : state.dataLoopNodes->Node(AirOutletNodeNum).MassFlowRate = state.dataLoopNodes->Node(AirInletNodeNum).MassFlowRate;
1052 112664 : state.dataLoopNodes->Node(AirOutletNodeNum).MassFlowRateMin = state.dataLoopNodes->Node(AirInletNodeNum).MassFlowRateMin;
1053 112664 : state.dataLoopNodes->Node(AirOutletNodeNum).MassFlowRateMax = state.dataLoopNodes->Node(AirInletNodeNum).MassFlowRateMax;
1054 112664 : state.dataLoopNodes->Node(AirOutletNodeNum).MassFlowRateMinAvail = state.dataLoopNodes->Node(AirInletNodeNum).MassFlowRateMinAvail;
1055 112664 : state.dataLoopNodes->Node(AirOutletNodeNum).MassFlowRateMaxAvail = state.dataLoopNodes->Node(AirInletNodeNum).MassFlowRateMaxAvail;
1056 :
1057 112664 : if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
1058 0 : state.dataLoopNodes->Node(AirOutletNodeNum).CO2 = state.dataLoopNodes->Node(AirInletNodeNum).CO2;
1059 : }
1060 112664 : if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
1061 0 : state.dataLoopNodes->Node(AirOutletNodeNum).GenContam = state.dataLoopNodes->Node(AirInletNodeNum).GenContam;
1062 : }
1063 112664 : }
1064 :
1065 112664 : void ReportZoneDehumidifier(EnergyPlusData &state, int const DehumidNum) // Index of the current zone dehumidifier being simulated
1066 : {
1067 :
1068 : // SUBROUTINE INFORMATION:
1069 : // AUTHOR Don Shirey, FSEC
1070 : // DATE WRITTEN August 2009
1071 : // MODIFIED na
1072 : // RE-ENGINEERED na
1073 :
1074 : // PURPOSE OF THIS SUBROUTINE:
1075 : // Fills some of the report variables for the zone dehumidifiers
1076 :
1077 : // METHODOLOGY EMPLOYED:
1078 : // na
1079 :
1080 : // REFERENCES:
1081 : // na
1082 :
1083 : // Using/Aliasing
1084 112664 : auto &TimeStepSys = state.dataHVACGlobal->TimeStepSys;
1085 : using Psychrometrics::RhoH2O;
1086 :
1087 : // Locals
1088 : // SUBROUTINE ARGUMENT DEFINITIONS:
1089 :
1090 : // SUBROUTINE PARAMETER DEFINITIONS:
1091 : // na
1092 :
1093 : // INTERFACE BLOCK SPECIFICATIONS:
1094 : // na
1095 :
1096 : // DERIVED TYPE DEFINITIONS:
1097 : // na
1098 :
1099 : // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
1100 : Real64 ReportingConstant; // Number of seconds per HVAC system time step, to convert from W (J/s) to J
1101 : Real64 RhoWater; // Density of condensate (water) being removed (kg/m3)
1102 : Real64 InletAirTemp; // Dry-bulb temperature of air entering the dehumidifier (C)
1103 : Real64 OutletAirTemp; // Dry-bulb temperature of air leaving the dehumidifier (C)
1104 : int AirInletNodeNum; // Node number corresponding to the air entering dehumidifier
1105 :
1106 112664 : ReportingConstant = TimeStepSys * DataGlobalConstants::SecInHour;
1107 :
1108 112664 : state.dataZoneDehumidifier->ZoneDehumid(DehumidNum).SensHeatingEnergy =
1109 112664 : state.dataZoneDehumidifier->ZoneDehumid(DehumidNum).SensHeatingRate * ReportingConstant;
1110 112664 : state.dataZoneDehumidifier->ZoneDehumid(DehumidNum).WaterRemoved =
1111 112664 : state.dataZoneDehumidifier->ZoneDehumid(DehumidNum).WaterRemovalRate * ReportingConstant;
1112 112664 : state.dataZoneDehumidifier->ZoneDehumid(DehumidNum).ElecConsumption =
1113 112664 : state.dataZoneDehumidifier->ZoneDehumid(DehumidNum).ElecPower * ReportingConstant;
1114 112664 : state.dataZoneDehumidifier->ZoneDehumid(DehumidNum).OffCycleParasiticElecCons =
1115 112664 : state.dataZoneDehumidifier->ZoneDehumid(DehumidNum).OffCycleParasiticElecPower * ReportingConstant;
1116 :
1117 : // Dehumidifier water collection to water storage tank (if needed)
1118 112664 : if (state.dataZoneDehumidifier->ZoneDehumid(DehumidNum).CondensateCollectMode == CondensateOutlet::ToTank) {
1119 : // Calculate and report condensation rate (how much water extracted from the air stream)
1120 : // Volumetric flow of water in m3/s for water system interactions
1121 :
1122 0 : AirInletNodeNum = state.dataZoneDehumidifier->ZoneDehumid(DehumidNum).AirInletNodeNum;
1123 0 : InletAirTemp = state.dataLoopNodes->Node(AirInletNodeNum).Temp;
1124 0 : OutletAirTemp = max((InletAirTemp - 11.0), 1.0); // Assume coil outlet air is 11C (20F) lower than inlet air temp
1125 0 : RhoWater = RhoH2O(OutletAirTemp); // Density of water, minimum temp = 1.0 C
1126 :
1127 0 : if (RhoWater > 0.0) {
1128 0 : state.dataZoneDehumidifier->ZoneDehumid(DehumidNum).DehumidCondVolFlowRate =
1129 0 : state.dataZoneDehumidifier->ZoneDehumid(DehumidNum).WaterRemovalRate / RhoWater;
1130 : }
1131 :
1132 0 : state.dataZoneDehumidifier->ZoneDehumid(DehumidNum).DehumidCondVol =
1133 0 : state.dataZoneDehumidifier->ZoneDehumid(DehumidNum).DehumidCondVolFlowRate * ReportingConstant;
1134 :
1135 0 : state.dataWaterData->WaterStorage(state.dataZoneDehumidifier->ZoneDehumid(DehumidNum).CondensateTankID)
1136 0 : .VdotAvailSupply(state.dataZoneDehumidifier->ZoneDehumid(DehumidNum).CondensateTankSupplyARRID) =
1137 0 : state.dataZoneDehumidifier->ZoneDehumid(DehumidNum).DehumidCondVolFlowRate;
1138 : // Assume water outlet temp = air outlet temp.... same assumption in other places in code (e.g., water coil component)
1139 0 : state.dataWaterData->WaterStorage(state.dataZoneDehumidifier->ZoneDehumid(DehumidNum).CondensateTankID)
1140 0 : .TwaterSupply(state.dataZoneDehumidifier->ZoneDehumid(DehumidNum).CondensateTankSupplyARRID) = OutletAirTemp;
1141 : }
1142 112664 : }
1143 :
1144 79 : bool GetZoneDehumidifierNodeNumber(EnergyPlusData &state, int const NodeNumber) // Node being tested
1145 : {
1146 :
1147 : // FUNCTION INFORMATION:
1148 : // AUTHOR Lixing Gu
1149 : // DATE WRITTEN August 2009
1150 : // MODIFIED na
1151 : // RE-ENGINEERED na
1152 :
1153 : // PURPOSE OF THIS FUNCTION:
1154 : // After making sure get input is done, the node number of indicated
1155 : // zone dehumidifier is returned.
1156 :
1157 : // Return value
1158 : bool FindZoneDehumidifierNodeNumber; // Zone Dehumidifier Node Number Check
1159 :
1160 79 : if (state.dataZoneDehumidifier->GetInputFlag) {
1161 22 : GetZoneDehumidifierInput(state);
1162 22 : state.dataZoneDehumidifier->GetInputFlag = false;
1163 : }
1164 :
1165 79 : FindZoneDehumidifierNodeNumber = false;
1166 86 : for (int ZoneDehumidIndex = 1; ZoneDehumidIndex <= (int)state.dataZoneDehumidifier->ZoneDehumid.size(); ++ZoneDehumidIndex) {
1167 9 : if (NodeNumber == state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).AirInletNodeNum) {
1168 1 : FindZoneDehumidifierNodeNumber = true;
1169 1 : break;
1170 : }
1171 8 : if (NodeNumber == state.dataZoneDehumidifier->ZoneDehumid(ZoneDehumidIndex).AirOutletNodeNum) {
1172 1 : FindZoneDehumidifierNodeNumber = true;
1173 1 : break;
1174 : }
1175 : }
1176 :
1177 79 : return FindZoneDehumidifierNodeNumber;
1178 : }
1179 :
1180 : } // namespace ZoneDehumidifier
1181 :
1182 2313 : } // namespace EnergyPlus
|