LCOV - code coverage report
Current view: top level - EnergyPlus - ZoneDehumidifier.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 307 495 62.0 %
Date: 2023-01-17 19:17:23 Functions: 9 9 100.0 %

          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

Generated by: LCOV version 1.13