LCOV - code coverage report
Current view: top level - EnergyPlus - Humidifiers.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 386 570 67.7 %
Date: 2024-08-23 23:50:59 Functions: 10 12 83.3 %

          Line data    Source code
       1             : // EnergyPlus, Copyright (c) 1996-2024, The Board of Trustees of the University of Illinois,
       2             : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
       3             : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
       4             : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
       5             : // contributors. All rights reserved.
       6             : //
       7             : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
       8             : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
       9             : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
      10             : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
      11             : // derivative works, and perform publicly and display publicly, and to permit others to do so.
      12             : //
      13             : // Redistribution and use in source and binary forms, with or without modification, are permitted
      14             : // provided that the following conditions are met:
      15             : //
      16             : // (1) Redistributions of source code must retain the above copyright notice, this list of
      17             : //     conditions and the following disclaimer.
      18             : //
      19             : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
      20             : //     conditions and the following disclaimer in the documentation and/or other materials
      21             : //     provided with the distribution.
      22             : //
      23             : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
      24             : //     the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
      25             : //     used to endorse or promote products derived from this software without specific prior
      26             : //     written permission.
      27             : //
      28             : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
      29             : //     without changes from the version obtained under this License, or (ii) Licensee makes a
      30             : //     reference solely to the software portion of its product, Licensee must refer to the
      31             : //     software as "EnergyPlus version X" software, where "X" is the version number Licensee
      32             : //     obtained under this License and may not use a different name for the software. Except as
      33             : //     specifically required in this Section (4), Licensee shall not use in a company name, a
      34             : //     product name, in advertising, publicity, or other promotional activities any name, trade
      35             : //     name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
      36             : //     similar designation, without the U.S. Department of Energy's prior written consent.
      37             : //
      38             : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
      39             : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
      40             : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
      41             : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      42             : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
      43             : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      44             : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
      45             : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      46             : // POSSIBILITY OF SUCH DAMAGE.
      47             : 
      48             : // ObjexxFCL Headers
      49             : #include <ObjexxFCL/Fmath.hh>
      50             : 
      51             : // EnergyPlus Headers
      52             : #include <EnergyPlus/Autosizing/Base.hh>
      53             : #include <EnergyPlus/BranchNodeConnections.hh>
      54             : #include <EnergyPlus/CurveManager.hh>
      55             : #include <EnergyPlus/Data/EnergyPlusData.hh>
      56             : #include <EnergyPlus/DataContaminantBalance.hh>
      57             : #include <EnergyPlus/DataEnvironment.hh>
      58             : #include <EnergyPlus/DataHVACGlobals.hh>
      59             : #include <EnergyPlus/DataIPShortCuts.hh>
      60             : #include <EnergyPlus/DataLoopNode.hh>
      61             : #include <EnergyPlus/DataSizing.hh>
      62             : #include <EnergyPlus/DataWater.hh>
      63             : #include <EnergyPlus/EMSManager.hh>
      64             : #include <EnergyPlus/FluidProperties.hh>
      65             : #include <EnergyPlus/General.hh>
      66             : #include <EnergyPlus/GeneralRoutines.hh>
      67             : #include <EnergyPlus/GlobalNames.hh>
      68             : #include <EnergyPlus/Humidifiers.hh>
      69             : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      70             : #include <EnergyPlus/NodeInputManager.hh>
      71             : #include <EnergyPlus/OutputProcessor.hh>
      72             : #include <EnergyPlus/Psychrometrics.hh>
      73             : #include <EnergyPlus/ScheduleManager.hh>
      74             : #include <EnergyPlus/UtilityRoutines.hh>
      75             : #include <EnergyPlus/WaterManager.hh>
      76             : 
      77             : namespace EnergyPlus {
      78             : 
      79             : namespace Humidifiers {
      80             : 
      81             :     // Module containing the routines dealing with humidifiers
      82             : 
      83             :     // MODULE INFORMATION:
      84             :     //       AUTHOR         Fred Buhl
      85             :     //       DATE WRITTEN   September 2000
      86             :     //       MODIFIED       B Griffith, Aug. 2006 added water system interactions
      87             :     //                        February 2015, B.Nigusse, FSEC, - transitioned the code
      88             :     //                        to object oriented approach and Added gas fired humidifier
      89             :     //       RE-ENGINEERED  na
      90             : 
      91             :     // PURPOSE OF THIS MODULE:
      92             :     // To encapsulate the data and routines required to model humidifier
      93             :     // components in the EnergyPlus HVAC simulation
      94             : 
      95             :     // METHODOLOGY EMPLOYED:
      96             :     // The humidifier encompasses not just the component but also its
      97             :     // control. The humidifier adds moisture to its air inlet to meet
      98             :     // the HumRatMin setpoint at its exit node. The HumRatMin is set by
      99             :     // an external setpoint manager.
     100             : 
     101             :     // REFERENCES: ASHRAE HVAC 2 Toolkit, page 4-112
     102             : 
     103             :     // Using/Aliasing
     104             :     using namespace DataLoopNode;
     105             :     using HVAC::SmallMassFlow;
     106             :     using namespace ScheduleManager;
     107             : 
     108     1294540 :     void SimHumidifier(EnergyPlusData &state,
     109             :                        std::string_view CompName,                      // name of the humidifier unit
     110             :                        [[maybe_unused]] bool const FirstHVACIteration, // TRUE if 1st HVAC simulation of system timestep
     111             :                        int &CompIndex                                  // Pointer to Humidifier Unit
     112             :     )
     113             :     {
     114             : 
     115             :         // SUBROUTINE INFORMATION:
     116             :         //       AUTHOR         Fred Buhl
     117             :         //       DATE WRITTEN   September 2000
     118             :         //       MODIFIED       February 2015, B. Nigusse, FSEC, - Added gas fired humidifier
     119             :         //       RE-ENGINEERED  na
     120             : 
     121             :         // PURPOSE OF THIS SUBROUTINE:
     122             :         // Manage the simulation of an air humidifier
     123             : 
     124             :         // Using/Aliasing
     125             : 
     126             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     127             :         int HumNum;            // index of humidifier unit being simulated
     128             :         Real64 WaterAddNeeded; // output in kg/s needed from humidifier to meet humidity setpoint
     129             : 
     130     1294540 :         auto &Humidifier = state.dataHumidifiers->Humidifier;
     131     1294540 :         int NumHumidifiers = state.dataHumidifiers->NumHumidifiers;
     132     1294540 :         auto &CheckEquipName = state.dataHumidifiers->CheckEquipName;
     133             : 
     134     1294540 :         if (state.dataHumidifiers->GetInputFlag) {
     135          24 :             GetHumidifierInput(state);
     136          24 :             state.dataHumidifiers->GetInputFlag = false;
     137             :         }
     138             : 
     139             :         // Get the humidifier unit index
     140     1294540 :         if (CompIndex == 0) {
     141          38 :             HumNum = Util::FindItemInList(CompName, Humidifier);
     142          38 :             if (HumNum == 0) {
     143           0 :                 ShowFatalError(state, format("SimHumidifier: Unit not found={}", CompName));
     144             :             }
     145          38 :             CompIndex = HumNum;
     146             :         } else {
     147     1294502 :             HumNum = CompIndex;
     148     1294502 :             if (HumNum > NumHumidifiers || HumNum < 1) {
     149           0 :                 ShowFatalError(
     150             :                     state,
     151           0 :                     format("SimHumidifier: Invalid CompIndex passed={}, Number of Units={}, Entered Unit name={}", HumNum, NumHumidifiers, CompName));
     152             :             }
     153     1294502 :             if (CheckEquipName(HumNum)) {
     154          38 :                 if (CompName != Humidifier(HumNum).Name) {
     155           0 :                     ShowFatalError(state,
     156           0 :                                    format("SimHumidifier: Invalid CompIndex passed={}, Unit name={}, stored Unit Name for that index={}",
     157             :                                           HumNum,
     158             :                                           CompName,
     159           0 :                                           Humidifier(HumNum).Name));
     160             :                 }
     161          38 :                 CheckEquipName(HumNum) = false;
     162             :             }
     163             :         }
     164     1294540 :         if (HumNum <= 0) {
     165           0 :             ShowFatalError(state, format("SimHumidifier: Unit not found={}", CompName));
     166             :         }
     167             : 
     168     1294540 :         auto &thisHum(Humidifier(HumNum));
     169             : 
     170     1294540 :         thisHum.InitHumidifier(state);
     171             : 
     172     1294540 :         thisHum.ControlHumidifier(state, WaterAddNeeded);
     173             : 
     174             :         // call the correct humidifier calculation routine
     175     1294540 :         switch (thisHum.HumType) {
     176     1268393 :         case HumidType::Electric: { // 'HUMIDIFIER:STEAM:ELECTRIC'
     177     1268393 :             thisHum.CalcElecSteamHumidifier(state, WaterAddNeeded);
     178     1268393 :         } break;
     179       26147 :         case HumidType::Gas: { // 'HUMIDIFIER:STEAM:GAS'
     180       26147 :             thisHum.CalcGasSteamHumidifier(state, WaterAddNeeded);
     181       26147 :         } break;
     182           0 :         default: {
     183           0 :             ShowSevereError(state, format("SimHumidifier: Invalid Humidifier Type Code={}", thisHum.HumType));
     184           0 :             ShowContinueError(state, format("...Component Name=[{}].", CompName));
     185           0 :             ShowFatalError(state, "Preceding Condition causes termination.");
     186           0 :         } break;
     187             :         }
     188             : 
     189     1294540 :         thisHum.UpdateReportWaterSystem(state);
     190             : 
     191     1294540 :         thisHum.UpdateHumidifier(state);
     192             : 
     193     1294540 :         thisHum.ReportHumidifier(state);
     194     1294540 :     }
     195             : 
     196          24 :     void GetHumidifierInput(EnergyPlusData &state)
     197             :     {
     198             : 
     199             :         // SUBROUTINE INFORMATION:
     200             :         //       AUTHOR         Fred Buhl
     201             :         //       DATE WRITTEN   September 2000
     202             :         //       MODIFIED       February 2015, B. Nigusse, FSEC, - Added gas fired humidifier
     203             :         //       RE-ENGINEERED  na
     204             : 
     205             :         // PURPOSE OF THIS SUBROUTINE:
     206             :         // Obtains input data for humidifiers and stores it in humidifier data structures.
     207             : 
     208             :         // METHODOLOGY EMPLOYED:
     209             :         // Uses InputProcessor "Get" routines to obtain data.
     210             : 
     211             :         // Using/Aliasing
     212             :         using BranchNodeConnections::TestCompSet;
     213             :         using Curve::GetCurveIndex;
     214             :         using NodeInputManager::GetOnlySingleNode;
     215             :         using WaterManager::SetupTankDemandComponent;
     216             :         using WaterManager::SetupTankSupplyComponent;
     217             : 
     218             :         // SUBROUTINE PARAMETER DEFINITIONS:
     219             :         static constexpr std::string_view RoutineName("GetHumidifierInputs: "); // include trailing blank space
     220             : 
     221             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     222             :         int HumidifierIndex;             // loop index
     223             :         int HumNum;                      // current humidifier number
     224             :         int NumAlphas;                   // Number of Alphas for each GetObjectItem call
     225             :         int NumNumbers;                  // Number of Numbers for each GetObjectItem call
     226             :         int MaxNums;                     // maximum Number of Numbers for each GetObjectItem call
     227             :         int MaxAlphas;                   // maximum Number of Numbers for each GetObjectItem call
     228             :         int IOStatus;                    // Used in GetObjectItem
     229          24 :         bool ErrorsFound(false);         // Set to true if errors in input, fatal at end of routine
     230          24 :         std::string CurrentModuleObject; // for ease in getting objects
     231          24 :         Array1D_string Alphas;           // Alpha input items for object
     232          24 :         Array1D_string cAlphaFields;     // Alpha field names
     233          24 :         Array1D_string cNumericFields;   // Numeric field names
     234          24 :         Array1D<Real64> Numbers;         // Numeric input items for object
     235          24 :         Array1D_bool lAlphaBlanks;       // Logical array, alpha field input BLANK = .TRUE.
     236          24 :         Array1D_bool lNumericBlanks;     // Logical array, numeric field input BLANK = .TRUE.
     237          24 :         int TotalArgs(0);                // Total number of alpha and numeric arguments (max) for a
     238             :         //  certain object in the input file
     239             : 
     240          24 :         auto &Humidifier = state.dataHumidifiers->Humidifier;
     241          24 :         auto &HumidifierUniqueNames = state.dataHumidifiers->HumidifierUniqueNames;
     242          24 :         auto &CheckEquipName = state.dataHumidifiers->CheckEquipName;
     243             : 
     244             :         // Update Nums in state and make local convenience copies
     245          24 :         CurrentModuleObject = "Humidifier:Steam:Electric";
     246          48 :         int NumElecSteamHums = state.dataHumidifiers->NumElecSteamHums =
     247          24 :             state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
     248          24 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, TotalArgs, NumAlphas, NumNumbers);
     249          24 :         MaxNums = NumNumbers;
     250          24 :         MaxAlphas = NumAlphas;
     251          24 :         CurrentModuleObject = "Humidifier:Steam:Gas";
     252          48 :         int NumGasSteamHums = state.dataHumidifiers->NumGasSteamHums =
     253          24 :             state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
     254          24 :         int NumHumidifiers = state.dataHumidifiers->NumHumidifiers = NumElecSteamHums + NumGasSteamHums;
     255          24 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(state, CurrentModuleObject, TotalArgs, NumAlphas, NumNumbers);
     256          24 :         MaxNums = max(MaxNums, NumNumbers);
     257          24 :         MaxAlphas = max(MaxAlphas, NumAlphas);
     258             : 
     259             :         // allocate the data array
     260          24 :         Humidifier.allocate(NumHumidifiers);
     261          24 :         HumidifierUniqueNames.reserve(static_cast<unsigned>(NumHumidifiers));
     262          24 :         CheckEquipName.dimension(NumHumidifiers, true);
     263             : 
     264          24 :         Alphas.allocate(MaxAlphas);
     265          24 :         cAlphaFields.allocate(MaxAlphas);
     266          24 :         cNumericFields.allocate(MaxNums);
     267          24 :         Numbers.dimension(MaxNums, 0.0);
     268          24 :         lAlphaBlanks.dimension(MaxAlphas, true);
     269          24 :         lNumericBlanks.dimension(MaxAlphas, true);
     270             : 
     271             :         // loop over electric steam humidifiers and load the input data
     272          24 :         CurrentModuleObject = "Humidifier:Steam:Electric";
     273          61 :         for (HumidifierIndex = 1; HumidifierIndex <= NumElecSteamHums; ++HumidifierIndex) {
     274          37 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
     275             :                                                                      CurrentModuleObject,
     276             :                                                                      HumidifierIndex,
     277             :                                                                      Alphas,
     278             :                                                                      NumAlphas,
     279             :                                                                      Numbers,
     280             :                                                                      NumNumbers,
     281             :                                                                      IOStatus,
     282             :                                                                      lNumericBlanks,
     283             :                                                                      lAlphaBlanks,
     284             :                                                                      cAlphaFields,
     285             :                                                                      cNumericFields);
     286          37 :             HumNum = HumidifierIndex;
     287          37 :             GlobalNames::VerifyUniqueInterObjectName(state, HumidifierUniqueNames, Alphas(1), CurrentModuleObject, cAlphaFields(1), ErrorsFound);
     288          37 :             Humidifier(HumNum).Name = Alphas(1);
     289             :             //    Humidifier(HumNum)%HumType = TRIM(CurrentModuleObject)
     290          37 :             Humidifier(HumNum).HumType = HumidType::Electric;
     291          37 :             Humidifier(HumNum).Sched = Alphas(2);
     292          37 :             if (lAlphaBlanks(2)) {
     293           1 :                 Humidifier(HumNum).SchedPtr = ScheduleManager::ScheduleAlwaysOn;
     294             :             } else {
     295          36 :                 Humidifier(HumNum).SchedPtr = GetScheduleIndex(state, Alphas(2)); // convert schedule name to pointer
     296          36 :                 if (Humidifier(HumNum).SchedPtr == 0) {
     297           0 :                     ShowSevereError(state,
     298           0 :                                     format("{}{}: invalid {} entered ={} for {}={}",
     299             :                                            RoutineName,
     300             :                                            CurrentModuleObject,
     301             :                                            cAlphaFields(2),
     302             :                                            Alphas(2),
     303             :                                            cAlphaFields(1),
     304             :                                            Alphas(1)));
     305           0 :                     ErrorsFound = true;
     306             :                 }
     307             :             }
     308          37 :             Humidifier(HumNum).NomCapVol = Numbers(1);
     309          37 :             Humidifier(HumNum).NomPower = Numbers(2);
     310          37 :             Humidifier(HumNum).FanPower = Numbers(3);
     311          37 :             Humidifier(HumNum).StandbyPower = Numbers(4);
     312          74 :             Humidifier(HumNum).AirInNode = GetOnlySingleNode(state,
     313          37 :                                                              Alphas(3),
     314             :                                                              ErrorsFound,
     315             :                                                              DataLoopNode::ConnectionObjectType::HumidifierSteamElectric,
     316          37 :                                                              Alphas(1),
     317             :                                                              DataLoopNode::NodeFluidType::Air,
     318             :                                                              DataLoopNode::ConnectionType::Inlet,
     319             :                                                              NodeInputManager::CompFluidStream::Primary,
     320             :                                                              ObjectIsNotParent);
     321          74 :             Humidifier(HumNum).AirOutNode = GetOnlySingleNode(state,
     322          37 :                                                               Alphas(4),
     323             :                                                               ErrorsFound,
     324             :                                                               DataLoopNode::ConnectionObjectType::HumidifierSteamElectric,
     325          37 :                                                               Alphas(1),
     326             :                                                               DataLoopNode::NodeFluidType::Air,
     327             :                                                               DataLoopNode::ConnectionType::Outlet,
     328             :                                                               NodeInputManager::CompFluidStream::Primary,
     329             :                                                               ObjectIsNotParent);
     330          37 :             TestCompSet(state, CurrentModuleObject, Alphas(1), Alphas(3), Alphas(4), "Air Nodes");
     331             : 
     332             :             //  A5; \field Name of Water Storage Tank
     333          37 :             if (lAlphaBlanks(5)) {
     334          37 :                 Humidifier(HumNum).SuppliedByWaterSystem = false;
     335             :             } else { // water from storage tank
     336           0 :                 SetupTankDemandComponent(state,
     337           0 :                                          Alphas(1),
     338             :                                          CurrentModuleObject,
     339           0 :                                          Alphas(5),
     340             :                                          ErrorsFound,
     341           0 :                                          Humidifier(HumNum).WaterTankID,
     342           0 :                                          Humidifier(HumNum).WaterTankDemandARRID);
     343           0 :                 Humidifier(HumNum).SuppliedByWaterSystem = true;
     344             :             }
     345             :         }
     346             : 
     347             :         // loop over gas fired steam humidifiers and load the input data
     348          24 :         CurrentModuleObject = "Humidifier:Steam:Gas";
     349          25 :         for (HumidifierIndex = 1; HumidifierIndex <= NumGasSteamHums; ++HumidifierIndex) {
     350           1 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
     351             :                                                                      CurrentModuleObject,
     352             :                                                                      HumidifierIndex,
     353             :                                                                      Alphas,
     354             :                                                                      NumAlphas,
     355             :                                                                      Numbers,
     356             :                                                                      NumNumbers,
     357             :                                                                      IOStatus,
     358             :                                                                      lNumericBlanks,
     359             :                                                                      lAlphaBlanks,
     360             :                                                                      cAlphaFields,
     361             :                                                                      cNumericFields);
     362           1 :             HumNum = NumElecSteamHums + HumidifierIndex;
     363           1 :             GlobalNames::VerifyUniqueInterObjectName(state, HumidifierUniqueNames, Alphas(1), CurrentModuleObject, cAlphaFields(1), ErrorsFound);
     364           1 :             Humidifier(HumNum).Name = Alphas(1);
     365           1 :             Humidifier(HumNum).HumType = HumidType::Gas;
     366           1 :             Humidifier(HumNum).Sched = Alphas(2);
     367           1 :             if (lAlphaBlanks(2)) {
     368           0 :                 Humidifier(HumNum).SchedPtr = ScheduleManager::ScheduleAlwaysOn;
     369             :             } else {
     370           1 :                 Humidifier(HumNum).SchedPtr = GetScheduleIndex(state, Alphas(2)); // convert schedule name to pointer
     371           1 :                 if (Humidifier(HumNum).SchedPtr == 0) {
     372           0 :                     ShowSevereError(state,
     373           0 :                                     format("{}{}: invalid {} entered ={} for {}={}",
     374             :                                            RoutineName,
     375             :                                            CurrentModuleObject,
     376             :                                            cAlphaFields(2),
     377             :                                            Alphas(2),
     378             :                                            cAlphaFields(1),
     379             :                                            Alphas(1)));
     380           0 :                     ErrorsFound = true;
     381             :                 }
     382             :             }
     383           1 :             Humidifier(HumNum).NomCapVol = Numbers(1);
     384           1 :             Humidifier(HumNum).NomPower = Numbers(2); // nominal gas use rate for gas fired steam humidifier
     385           1 :             Humidifier(HumNum).ThermalEffRated = Numbers(3);
     386           1 :             Humidifier(HumNum).FanPower = Numbers(4);
     387           1 :             Humidifier(HumNum).StandbyPower = Numbers(5);
     388           2 :             Humidifier(HumNum).AirInNode = GetOnlySingleNode(state,
     389           1 :                                                              Alphas(4),
     390             :                                                              ErrorsFound,
     391             :                                                              DataLoopNode::ConnectionObjectType::HumidifierSteamGas,
     392           1 :                                                              Alphas(1),
     393             :                                                              DataLoopNode::NodeFluidType::Air,
     394             :                                                              DataLoopNode::ConnectionType::Inlet,
     395             :                                                              NodeInputManager::CompFluidStream::Primary,
     396             :                                                              ObjectIsNotParent);
     397           2 :             Humidifier(HumNum).AirOutNode = GetOnlySingleNode(state,
     398           1 :                                                               Alphas(5),
     399             :                                                               ErrorsFound,
     400             :                                                               DataLoopNode::ConnectionObjectType::HumidifierSteamGas,
     401           1 :                                                               Alphas(1),
     402             :                                                               DataLoopNode::NodeFluidType::Air,
     403             :                                                               DataLoopNode::ConnectionType::Outlet,
     404             :                                                               NodeInputManager::CompFluidStream::Primary,
     405             :                                                               ObjectIsNotParent);
     406           1 :             TestCompSet(state, CurrentModuleObject, Alphas(1), Alphas(4), Alphas(5), "Air Nodes");
     407             : 
     408           1 :             Humidifier(HumNum).EfficiencyCurvePtr = GetCurveIndex(state, Alphas(3));
     409           1 :             if (Humidifier(HumNum).EfficiencyCurvePtr > 0) {
     410           2 :                 ErrorsFound |= Curve::CheckCurveDims(state,
     411           1 :                                                      Humidifier(HumNum).EfficiencyCurvePtr, // Curve index
     412             :                                                      {1},                                   // Valid dimensions
     413             :                                                      RoutineName,                           // Routine name
     414             :                                                      CurrentModuleObject,                   // Object Type
     415           1 :                                                      Humidifier(HumNum).Name,               // Object Name
     416           1 :                                                      cAlphaFields(3));                      // Field Name
     417           0 :             } else if (!lAlphaBlanks(3)) {
     418           0 :                 ShowSevereError(state, format("{}{}=\"{}\",", RoutineName, CurrentModuleObject, Alphas(1)));
     419           0 :                 ShowContinueError(state, format("Invalid {}={}", cAlphaFields(3), Alphas(3)));
     420           0 :                 ShowContinueError(state, format("...{} not found.", cAlphaFields(3)));
     421           0 :                 ErrorsFound = true;
     422             :             }
     423             : 
     424             :             //  A6; \field Name of Water Storage Tank
     425           1 :             if (lAlphaBlanks(6)) {
     426           1 :                 Humidifier(HumNum).SuppliedByWaterSystem = false;
     427             :             } else { // water from storage tank
     428           0 :                 SetupTankDemandComponent(state,
     429           0 :                                          Alphas(1),
     430             :                                          CurrentModuleObject,
     431           0 :                                          Alphas(6),
     432             :                                          ErrorsFound,
     433           0 :                                          Humidifier(HumNum).WaterTankID,
     434           0 :                                          Humidifier(HumNum).WaterTankDemandARRID);
     435           0 :                 SetupTankSupplyComponent(
     436           0 :                     state, Alphas(1), CurrentModuleObject, Alphas(6), ErrorsFound, Humidifier(HumNum).WaterTankID, Humidifier(HumNum).TankSupplyID);
     437           0 :                 Humidifier(HumNum).SuppliedByWaterSystem = true;
     438             :             }
     439             : 
     440             :             // A7; \field Inlet Water Temperature Option
     441           1 :             if (lAlphaBlanks(7)) {
     442           1 :                 Humidifier(HumNum).InletWaterTempOption = InletWaterTemp::Fixed;
     443             :             } else { // water from storage tank
     444           0 :                 Humidifier(HumNum).InletWaterTempOption = static_cast<InletWaterTemp>(getEnumValue(inletWaterTempsUC, Alphas(7)));
     445             :             }
     446             :         }
     447             : 
     448          62 :         for (HumNum = 1; HumNum <= NumHumidifiers; ++HumNum) {
     449             :             // Setup Report variables for the Humidifiers
     450          38 :             if (Humidifier(HumNum).SuppliedByWaterSystem) {
     451           0 :                 SetupOutputVariable(state,
     452             :                                     "Humidifier Water Volume Flow Rate",
     453             :                                     Constant::Units::m3_s,
     454           0 :                                     Humidifier(HumNum).WaterConsRate,
     455             :                                     OutputProcessor::TimeStepType::System,
     456             :                                     OutputProcessor::StoreType::Average,
     457           0 :                                     Humidifier(HumNum).Name);
     458           0 :                 SetupOutputVariable(state,
     459             :                                     "Humidifier Water Volume",
     460             :                                     Constant::Units::m3,
     461           0 :                                     Humidifier(HumNum).WaterCons,
     462             :                                     OutputProcessor::TimeStepType::System,
     463             :                                     OutputProcessor::StoreType::Sum,
     464           0 :                                     Humidifier(HumNum).Name);
     465           0 :                 SetupOutputVariable(state,
     466             :                                     "Humidifier Storage Tank Water Volume Flow Rate",
     467             :                                     Constant::Units::m3_s,
     468           0 :                                     Humidifier(HumNum).TankSupplyVdot,
     469             :                                     OutputProcessor::TimeStepType::System,
     470             :                                     OutputProcessor::StoreType::Average,
     471           0 :                                     Humidifier(HumNum).Name);
     472           0 :                 SetupOutputVariable(state,
     473             :                                     "Humidifier Storage Tank Water Volume",
     474             :                                     Constant::Units::m3,
     475           0 :                                     Humidifier(HumNum).TankSupplyVol,
     476             :                                     OutputProcessor::TimeStepType::System,
     477             :                                     OutputProcessor::StoreType::Sum,
     478           0 :                                     Humidifier(HumNum).Name,
     479             :                                     Constant::eResource::Water,
     480             :                                     OutputProcessor::Group::HVAC,
     481             :                                     OutputProcessor::EndUseCat::Humidification);
     482           0 :                 SetupOutputVariable(state,
     483             :                                     "Humidifier Starved Storage Tank Water Volume Flow Rate",
     484             :                                     Constant::Units::m3_s,
     485           0 :                                     Humidifier(HumNum).StarvedSupplyVdot,
     486             :                                     OutputProcessor::TimeStepType::System,
     487             :                                     OutputProcessor::StoreType::Average,
     488           0 :                                     Humidifier(HumNum).Name);
     489           0 :                 SetupOutputVariable(state,
     490             :                                     "Humidifier Starved Storage Tank Water Volume",
     491             :                                     Constant::Units::m3,
     492           0 :                                     Humidifier(HumNum).StarvedSupplyVol,
     493             :                                     OutputProcessor::TimeStepType::System,
     494             :                                     OutputProcessor::StoreType::Sum,
     495           0 :                                     Humidifier(HumNum).Name,
     496             :                                     Constant::eResource::Water,
     497             :                                     OutputProcessor::Group::HVAC,
     498             :                                     OutputProcessor::EndUseCat::Humidification);
     499           0 :                 SetupOutputVariable(state,
     500             :                                     "Humidifier Mains Water Volume",
     501             :                                     Constant::Units::m3,
     502           0 :                                     Humidifier(HumNum).StarvedSupplyVol,
     503             :                                     OutputProcessor::TimeStepType::System,
     504             :                                     OutputProcessor::StoreType::Sum,
     505           0 :                                     Humidifier(HumNum).Name,
     506             :                                     Constant::eResource::MainsWater,
     507             :                                     OutputProcessor::Group::HVAC,
     508             :                                     OutputProcessor::EndUseCat::Humidification);
     509             : 
     510             :             } else {
     511          76 :                 SetupOutputVariable(state,
     512             :                                     "Humidifier Water Volume Flow Rate",
     513             :                                     Constant::Units::m3_s,
     514          38 :                                     Humidifier(HumNum).WaterConsRate,
     515             :                                     OutputProcessor::TimeStepType::System,
     516             :                                     OutputProcessor::StoreType::Average,
     517          38 :                                     Humidifier(HumNum).Name);
     518          76 :                 SetupOutputVariable(state,
     519             :                                     "Humidifier Water Volume",
     520             :                                     Constant::Units::m3,
     521          38 :                                     Humidifier(HumNum).WaterCons,
     522             :                                     OutputProcessor::TimeStepType::System,
     523             :                                     OutputProcessor::StoreType::Sum,
     524          38 :                                     Humidifier(HumNum).Name,
     525             :                                     Constant::eResource::Water,
     526             :                                     OutputProcessor::Group::HVAC,
     527             :                                     OutputProcessor::EndUseCat::Humidification);
     528          76 :                 SetupOutputVariable(state,
     529             :                                     "Humidifier Mains Water Volume",
     530             :                                     Constant::Units::m3,
     531          38 :                                     Humidifier(HumNum).WaterCons,
     532             :                                     OutputProcessor::TimeStepType::System,
     533             :                                     OutputProcessor::StoreType::Sum,
     534          38 :                                     Humidifier(HumNum).Name,
     535             :                                     Constant::eResource::MainsWater,
     536             :                                     OutputProcessor::Group::HVAC,
     537             :                                     OutputProcessor::EndUseCat::Humidification);
     538             :             }
     539          38 :             if (Humidifier(HumNum).HumType == HumidType::Electric) {
     540          74 :                 SetupOutputVariable(state,
     541             :                                     "Humidifier Electricity Rate",
     542             :                                     Constant::Units::W,
     543          37 :                                     Humidifier(HumNum).ElecUseRate,
     544             :                                     OutputProcessor::TimeStepType::System,
     545             :                                     OutputProcessor::StoreType::Average,
     546          37 :                                     Humidifier(HumNum).Name);
     547          74 :                 SetupOutputVariable(state,
     548             :                                     "Humidifier Electricity Energy",
     549             :                                     Constant::Units::J,
     550          37 :                                     Humidifier(HumNum).ElecUseEnergy,
     551             :                                     OutputProcessor::TimeStepType::System,
     552             :                                     OutputProcessor::StoreType::Sum,
     553          37 :                                     Humidifier(HumNum).Name,
     554             :                                     Constant::eResource::Electricity,
     555             :                                     OutputProcessor::Group::HVAC,
     556             :                                     OutputProcessor::EndUseCat::Humidification);
     557           1 :             } else if (Humidifier(HumNum).HumType == HumidType::Gas) {
     558           2 :                 SetupOutputVariable(state,
     559             :                                     "Humidifier NaturalGas Use Thermal Efficiency",
     560             :                                     Constant::Units::None,
     561           1 :                                     Humidifier(HumNum).ThermalEff,
     562             :                                     OutputProcessor::TimeStepType::System,
     563             :                                     OutputProcessor::StoreType::Average,
     564           1 :                                     Humidifier(HumNum).Name);
     565           2 :                 SetupOutputVariable(state,
     566             :                                     "Humidifier NaturalGas Rate",
     567             :                                     Constant::Units::W,
     568           1 :                                     Humidifier(HumNum).GasUseRate,
     569             :                                     OutputProcessor::TimeStepType::System,
     570             :                                     OutputProcessor::StoreType::Average,
     571           1 :                                     Humidifier(HumNum).Name);
     572           2 :                 SetupOutputVariable(state,
     573             :                                     "Humidifier NaturalGas Energy",
     574             :                                     Constant::Units::J,
     575           1 :                                     Humidifier(HumNum).GasUseEnergy,
     576             :                                     OutputProcessor::TimeStepType::System,
     577             :                                     OutputProcessor::StoreType::Sum,
     578           1 :                                     Humidifier(HumNum).Name,
     579             :                                     Constant::eResource::NaturalGas,
     580             :                                     OutputProcessor::Group::HVAC,
     581             :                                     OutputProcessor::EndUseCat::Humidification);
     582           2 :                 SetupOutputVariable(state,
     583             :                                     "Humidifier Auxiliary Electricity Rate",
     584             :                                     Constant::Units::W,
     585           1 :                                     Humidifier(HumNum).AuxElecUseRate,
     586             :                                     OutputProcessor::TimeStepType::System,
     587             :                                     OutputProcessor::StoreType::Average,
     588           1 :                                     Humidifier(HumNum).Name);
     589           2 :                 SetupOutputVariable(state,
     590             :                                     "Humidifier Auxiliary Electricity Energy",
     591             :                                     Constant::Units::J,
     592           1 :                                     Humidifier(HumNum).AuxElecUseEnergy,
     593             :                                     OutputProcessor::TimeStepType::System,
     594             :                                     OutputProcessor::StoreType::Sum,
     595           1 :                                     Humidifier(HumNum).Name,
     596             :                                     Constant::eResource::Electricity,
     597             :                                     OutputProcessor::Group::HVAC,
     598             :                                     OutputProcessor::EndUseCat::Humidification);
     599             :             }
     600             :         }
     601             : 
     602          24 :         Alphas.deallocate();
     603          24 :         cAlphaFields.deallocate();
     604          24 :         cNumericFields.deallocate();
     605          24 :         Numbers.deallocate();
     606          24 :         lAlphaBlanks.deallocate();
     607          24 :         lNumericBlanks.deallocate();
     608             : 
     609          24 :         if (ErrorsFound) {
     610           0 :             ShowFatalError(state, format("{}Errors found in input.", RoutineName));
     611             :         }
     612          24 :     }
     613             : 
     614     1294540 :     void HumidifierData::InitHumidifier(EnergyPlusData &state) // number of the current humidifier being simulated
     615             :     {
     616             : 
     617             :         // SUBROUTINE INFORMATION:
     618             :         //       AUTHOR         Fred Buhl
     619             :         //       DATE WRITTEN   September 2000
     620             :         //       MODIFIED       February 2015, B. Nigusse, FSEC, - Added gas fired humidifier
     621             :         //       RE-ENGINEERED  na
     622             : 
     623             :         // PURPOSE OF THIS SUBROUTINE:
     624             :         // This subroutine is for initializations of the Humidifier Components.
     625             : 
     626             :         // METHODOLOGY EMPLOYED:
     627             :         // Uses the status flags to trigger initializations.
     628             : 
     629             :         // REFERENCES:
     630             :         // na
     631             : 
     632             :         // Using/Aliasing
     633             :         using EMSManager::CheckIfNodeSetPointManagedByEMS;
     634             : 
     635             :         // Locals
     636             :         // SUBROUTINE ARGUMENT DEFINITIONS:
     637             : 
     638             :         // do sizing calculation once
     639     1294540 :         if (MySizeFlag) {
     640          38 :             SizeHumidifier(state);
     641          38 :             MySizeFlag = false;
     642             :         }
     643             : 
     644     1294540 :         if (!state.dataGlobal->SysSizingCalc && MySetPointCheckFlag && state.dataHVACGlobal->DoSetPointTest) {
     645          38 :             if (AirOutNode > 0) {
     646          38 :                 if (state.dataLoopNodes->Node(AirOutNode).HumRatMin == SensedNodeFlagValue) {
     647           0 :                     if (!state.dataGlobal->AnyEnergyManagementSystemInModel) {
     648           0 :                         ShowSevereError(
     649             :                             state,
     650           0 :                             format("Humidifiers: Missing humidity setpoint for {} = {}", format(HumidifierType[static_cast<int>(HumType)]), Name));
     651           0 :                         ShowContinueError(state,
     652             :                                           "  use a Setpoint Manager with Control Variable = \"MinimumHumidityRatio\" to establish a setpoint at the "
     653             :                                           "humidifier outlet node.");
     654           0 :                         ShowContinueError(state, format("  expecting it on Node=\"{}\".", state.dataLoopNodes->NodeID(AirOutNode)));
     655           0 :                         state.dataHVACGlobal->SetPointErrorFlag = true;
     656             :                     } else {
     657           0 :                         CheckIfNodeSetPointManagedByEMS(state, AirOutNode, HVAC::CtrlVarType::MinHumRat, state.dataHVACGlobal->SetPointErrorFlag);
     658           0 :                         if (state.dataHVACGlobal->SetPointErrorFlag) {
     659           0 :                             ShowSevereError(state,
     660           0 :                                             format("Humidifiers: Missing humidity setpoint for {} = {}",
     661           0 :                                                    format(HumidifierType[static_cast<int>(HumType)]),
     662           0 :                                                    Name));
     663           0 :                             ShowContinueError(state,
     664             :                                               "  use a Setpoint Manager with Control Variable = \"MinimumHumidityRatio\" to establish a setpoint at "
     665             :                                               "the humidifier outlet node.");
     666           0 :                             ShowContinueError(state, format("  expecting it on Node=\"{}\".", state.dataLoopNodes->NodeID(AirOutNode)));
     667           0 :                             ShowContinueError(
     668             :                                 state,
     669             :                                 "  or use an EMS actuator to control minimum humidity ratio to establish a setpoint at the humidifier outlet node.");
     670             :                         }
     671             :                     }
     672             :                 }
     673             :             }
     674          38 :             MySetPointCheckFlag = false;
     675             :         }
     676             : 
     677     1294540 :         if (!state.dataGlobal->BeginEnvrnFlag) {
     678     1287861 :             MyEnvrnFlag = true;
     679             :         }
     680             : 
     681             :         // do these initializations every HVAC time step
     682     1294540 :         HumRatSet = state.dataLoopNodes->Node(AirOutNode).HumRatMin;
     683     1294540 :         AirInTemp = state.dataLoopNodes->Node(AirInNode).Temp;
     684     1294540 :         AirInHumRat = state.dataLoopNodes->Node(AirInNode).HumRat;
     685     1294540 :         AirInEnthalpy = state.dataLoopNodes->Node(AirInNode).Enthalpy;
     686     1294540 :         AirInMassFlowRate = state.dataLoopNodes->Node(AirInNode).MassFlowRate;
     687             : 
     688     1294540 :         WaterAdd = 0.0;
     689     1294540 :         ElecUseEnergy = 0.0;
     690     1294540 :         ElecUseRate = 0.0;
     691     1294540 :         WaterCons = 0.0;
     692     1294540 :         WaterConsRate = 0.0;
     693     1294540 :         ThermalEff = 0.0;
     694     1294540 :         GasUseRate = 0.0;
     695     1294540 :         GasUseEnergy = 0.0;
     696     1294540 :         AuxElecUseRate = 0.0;
     697     1294540 :         AuxElecUseEnergy = 0.0;
     698     1294540 :     }
     699             : 
     700          38 :     void HumidifierData::SizeHumidifier(EnergyPlusData &state) // number of the current humidifier being sized
     701             :     {
     702             : 
     703             :         // SUBROUTINE INFORMATION:
     704             :         //       AUTHOR         Bereket Nigusse, UCF/FSEC,
     705             :         //       DATE WRITTEN   March, 2012
     706             :         //       MODIFIED       May 2014, Daeho Kang, PNNL - Added additional sizing field
     707             :         //                        February 2015, B. Nigusse, FSEC, - Added gas fired humidifier
     708             :         //       RE-ENGINEERED  na
     709             : 
     710             :         // PURPOSE OF THIS SUBROUTINE:
     711             :         // This subroutine is for for sizing electric steam humidifier nominal electric power.
     712             : 
     713             :         // METHODOLOGY EMPLOYED:
     714             :         // Uses user specified nominal capacity in m3/s and water enthalpy change required to
     715             :         // vaporize water from a reference temperature of 20.0C. to steam at 100.0C.
     716             :         //  m_dot = Nominal Capacity [m3/s] * Density of water at 5.05 [kg/m3]
     717             :         //  Nominal Capacity =  m_dot [kg/s] * delta_enthalpy [J/kg]
     718             : 
     719             :         // REFERENCES:
     720             :         // na
     721             : 
     722             :         // Using/Aliasing
     723             :         using DataSizing::AutoSize;
     724             :         using FluidProperties::GetSatEnthalpyRefrig;
     725             :         using FluidProperties::GetSpecificHeatGlycol;
     726             : 
     727             :         using Psychrometrics::PsyRhoAirFnPbTdbW;
     728             :         using Psychrometrics::RhoH2O;
     729             : 
     730             :         // Locals
     731             :         // SUBROUTINE ARGUMENT DEFINITIONS:
     732             : 
     733             :         // SUBROUTINE PARAMETER DEFINITIONS:
     734             :         static constexpr std::string_view CalledFrom("Humidifier:SizeHumidifier");
     735          38 :         Real64 constexpr Tref(20.0);    // Reference temp of water for rated capacity calcs [C]
     736          38 :         Real64 constexpr TSteam(100.0); // saturated steam temperature generated by Humidifier [C]
     737             : 
     738             :         // INTERFACE BLOCK SPECIFICATIONS
     739             :         // na
     740             : 
     741             :         // DERIVED TYPE DEFINITIONS
     742             :         // na
     743             : 
     744             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     745          38 :         std::string ModuleObjectType; // for ease in getting objects
     746             :         int RefrigerantIndex;         // refrigerant index
     747             :         int WaterIndex;               // fluid type index
     748             :         Real64 NominalPower;          // Nominal power input to humidifier, W
     749             :         Real64 WaterSpecHeatAvg;      // specific heat of water, J/kgK
     750             :         Real64 SteamSatEnthalpy;      // enthalpy of saturated steam at 100C, J/kg
     751             :         Real64 WaterSatEnthalpy;      // enthalpy of saturated water at 100C, J/kg
     752             :         bool IsAutoSize;              // Indicator to autosize
     753             :         bool HardSizeNoDesRun;        // Indicator to a hard-sized field with no design sizing data
     754          38 :         bool ErrorsFound(false);      // TRUE if errors detected in input
     755             :         Real64 NomPowerDes;           // Autosized nominal power for reporting
     756             :         Real64 NomPowerUser;          // Hardsized nominal power for reporting
     757             :         Real64 MassFlowDes;           // Design air mass flow rate
     758             :         Real64 InletHumRatDes;        // Design inlet humidity ratio
     759             :         Real64 OutletHumRatDes;       // Design outlet humidity ratio
     760             :         Real64 NomCapVolDes;          // Autosized Nominal capacity volume for reporting
     761             :         Real64 NomCapVolUser;         // HardSized nominal capacity volume for reporting
     762             :         Real64 AirVolFlow;            // Design air volume flow rate
     763             :         Real64 AirDensity;            // Density of air
     764             : 
     765          38 :         if (HumType == HumidType::Electric || HumType == HumidType::Gas) {
     766          38 :             IsAutoSize = false;
     767          38 :             HardSizeNoDesRun = false;
     768          38 :             NomPowerDes = 0.0;
     769          38 :             NomPowerUser = 0.0;
     770             : 
     771          38 :             if (HumType == HumidType::Electric) {
     772          37 :                 ModuleObjectType = "electric";
     773           1 :             } else if (HumType == HumidType::Gas) {
     774           1 :                 ModuleObjectType = "gas";
     775             :             }
     776          38 :             if (NomCapVol == AutoSize) {
     777           2 :                 IsAutoSize = true;
     778             :             }
     779          38 :             if (state.dataSize->CurZoneEqNum > 0) {
     780           0 :                 if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) { // Hardsize with no sizing run
     781           0 :                     HardSizeNoDesRun = true;
     782           0 :                     if (NomCapVol > 0.0) {
     783           0 :                         BaseSizer::reportSizerOutput(state,
     784           0 :                                                      format(HumidifierType[static_cast<int>(HumType)]),
     785             :                                                      Name,
     786             :                                                      "User-Specified Nominal Capacity Volume [m3/s]",
     787             :                                                      NomCapVol);
     788             :                     }
     789             :                 } else { // Sizing run done
     790             : 
     791           0 :                     CheckZoneSizing(state, "Humidifier:SizeHumidifier", Name);
     792           0 :                     AirDensity = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).DesCoolDens;
     793           0 :                     MassFlowDes = max(state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).DesCoolVolFlow,
     794           0 :                                       state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).DesHeatVolFlow) *
     795             :                                   AirDensity;
     796           0 :                     InletHumRatDes = std::min(state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).OutHumRatAtHeatPeak,
     797           0 :                                               state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).OutHumRatAtCoolPeak);
     798           0 :                     OutletHumRatDes = std::max(state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).ZoneHumRatAtHeatPeak,
     799           0 :                                                state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).ZoneHumRatAtCoolPeak);
     800             :                 }
     801          38 :             } else if (state.dataSize->CurSysNum > 0) {
     802          38 :                 if (!IsAutoSize && !state.dataSize->SysSizingRunDone) {
     803           3 :                     HardSizeNoDesRun = true;
     804           3 :                     if (NomCapVol > 0.0) {
     805           9 :                         BaseSizer::reportSizerOutput(state,
     806           6 :                                                      format(HumidifierType[static_cast<int>(HumType)]),
     807             :                                                      Name,
     808             :                                                      "User-Specified Nominal Capacity Volume [m3/s]",
     809             :                                                      NomCapVol);
     810             :                     }
     811             :                 } else {
     812          35 :                     CheckSysSizing(state, "Humidifier:SizeHumidifier", Name);
     813          35 :                     auto &thisFinalSysSizing = state.dataSize->FinalSysSizing(state.dataSize->CurSysNum);
     814          35 :                     if (state.dataSize->CurOASysNum > 0 && thisFinalSysSizing.DesOutAirVolFlow > 0.0) {
     815             :                         // size to outdoor air volume flow rate if available
     816           1 :                         AirDensity = PsyRhoAirFnPbTdbW(
     817           1 :                             state, state.dataEnvrn->OutBaroPress, state.dataEnvrn->OutDryBulbTemp, state.dataEnvrn->OutHumRat, CalledFrom);
     818           1 :                         MassFlowDes = thisFinalSysSizing.DesOutAirVolFlow * AirDensity;
     819           1 :                         InletHumRatDes = std::min(thisFinalSysSizing.OutHumRatAtCoolPeak, thisFinalSysSizing.HeatOutHumRat);
     820           1 :                         OutletHumRatDes = std::max(thisFinalSysSizing.CoolSupHumRat, thisFinalSysSizing.HeatSupHumRat);
     821             :                     } else { // ELSE size to supply air duct flow rate
     822          34 :                         switch (state.dataSize->CurDuctType) {
     823           0 :                         case HVAC::AirDuctType::Cooling: {
     824           0 :                             AirVolFlow = thisFinalSysSizing.DesCoolVolFlow;
     825           0 :                         } break;
     826           1 :                         case HVAC::AirDuctType::Heating: {
     827           1 :                             AirVolFlow = thisFinalSysSizing.DesHeatVolFlow;
     828           1 :                         } break;
     829          33 :                         default: {
     830          33 :                             AirVolFlow = thisFinalSysSizing.DesMainVolFlow;
     831          33 :                         } break;
     832             :                         }
     833             : 
     834          34 :                         AirDensity = PsyRhoAirFnPbTdbW(state,
     835          34 :                                                        state.dataEnvrn->OutBaroPress,
     836             :                                                        thisFinalSysSizing.MixTempAtCoolPeak,
     837             :                                                        thisFinalSysSizing.MixHumRatAtCoolPeak,
     838             :                                                        CalledFrom);
     839          34 :                         MassFlowDes = AirVolFlow * AirDensity;
     840          34 :                         InletHumRatDes = std::min(thisFinalSysSizing.MixHumRatAtCoolPeak, thisFinalSysSizing.HeatMixHumRat);
     841          34 :                         OutletHumRatDes = std::max(thisFinalSysSizing.CoolSupHumRat, thisFinalSysSizing.HeatSupHumRat);
     842             :                     }
     843             :                 }
     844             :             }
     845             : 
     846          38 :             if (!HardSizeNoDesRun) {
     847          35 :                 NomCapVolDes = MassFlowDes * (OutletHumRatDes - InletHumRatDes) / RhoH2O(Constant::InitConvTemp);
     848          35 :                 if (NomCapVolDes < 0.0) NomCapVolDes = 0.0; // No humidity demand
     849             : 
     850          35 :                 if (IsAutoSize) {
     851           2 :                     NomCapVol = NomCapVolDes;
     852           6 :                     BaseSizer::reportSizerOutput(
     853           4 :                         state, format(HumidifierType[static_cast<int>(HumType)]), Name, "Design Size Nominal Capacity Volume [m3/s]", NomCapVolDes);
     854             :                 } else {
     855          33 :                     if (NomCapVol > 0.0) {
     856          33 :                         NomCapVolUser = NomCapVol;
     857          99 :                         BaseSizer::reportSizerOutput(state,
     858          66 :                                                      format(HumidifierType[static_cast<int>(HumType)]),
     859             :                                                      Name,
     860             :                                                      "Design Size Nominal Capacity Volume [m3/s]",
     861             :                                                      NomCapVolDes,
     862             :                                                      "User-Specified Nominal Capacity Volume [m3/s]",
     863             :                                                      NomCapVolUser);
     864          33 :                         if (state.dataGlobal->DisplayExtraWarnings) {
     865           0 :                             if ((std::abs(NomCapVolDes - NomCapVolUser) / NomCapVolUser) > state.dataSize->AutoVsHardSizingThreshold) {
     866           0 :                                 ShowMessage(state,
     867           0 :                                             format("SizeHumidifier: Potential issue with equipment sizing for {} = \"{}\".",
     868           0 :                                                    format(HumidifierType[static_cast<int>(HumType)]),
     869           0 :                                                    Name));
     870           0 :                                 ShowContinueError(state, format("User-Specified Nominal Capacity Volume of {:.2R} [Wm3/s]", NomCapVolUser));
     871           0 :                                 ShowContinueError(state, format("differs from Design Size Nominal Capacity Volume of {:.2R} [m3/s]", NomCapVolDes));
     872           0 :                                 ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
     873           0 :                                 ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
     874             :                             }
     875             :                         }
     876             :                     }
     877             :                 }
     878             :             }
     879             : 
     880          38 :             NomCap = RhoH2O(Constant::InitConvTemp) * NomCapVol;
     881          38 :             RefrigerantIndex = FluidProperties::GetRefrigNum(state, format(fluidNameSteam));
     882          38 :             WaterIndex = FluidProperties::GetGlycolNum(state, format(fluidNameWater));
     883          38 :             SteamSatEnthalpy = GetSatEnthalpyRefrig(state, format(fluidNameSteam), TSteam, 1.0, RefrigerantIndex, CalledFrom);
     884          38 :             WaterSatEnthalpy = GetSatEnthalpyRefrig(state, format(fluidNameSteam), TSteam, 0.0, RefrigerantIndex, CalledFrom);
     885          38 :             WaterSpecHeatAvg = 0.5 * (GetSpecificHeatGlycol(state, format(fluidNameWater), TSteam, WaterIndex, CalledFrom) +
     886          38 :                                       GetSpecificHeatGlycol(state, format(fluidNameWater), Tref, WaterIndex, CalledFrom));
     887          38 :             NominalPower = NomCap * ((SteamSatEnthalpy - WaterSatEnthalpy) + WaterSpecHeatAvg * (TSteam - Tref));
     888             : 
     889          38 :             if (NomPower == AutoSize) {
     890           4 :                 IsAutoSize = true;
     891             :             }
     892             : 
     893          38 :             if (HumType == HumidType::Gas) {
     894             : 
     895           1 :                 if (!IsAutoSize) {
     896             :                     // override user specified rated thermal efficiency
     897           0 :                     if (NomPower >= NominalPower) {
     898           0 :                         ThermalEffRated = NominalPower / NomPower;
     899             :                     } else {
     900           0 :                         ShowMessage(state,
     901           0 :                                     format("{}: capacity and thermal efficiency mismatch for {} =\"{}\".",
     902             :                                            CalledFrom,
     903           0 :                                            format(HumidifierType[static_cast<int>(HumType)]),
     904           0 :                                            Name));
     905           0 :                         ShowContinueError(state, format("User-Specified Rated Gas Use Rate of {:.2R} [W]", NomPower));
     906           0 :                         ShowContinueError(state, format("User-Specified or Autosized Rated Capacity of {:.2R} [m3/s]", NomCapVol));
     907           0 :                         ShowContinueError(state,
     908           0 :                                           format("Rated Gas Use Rate at the Rated Capacity of {:.2R} [m3/s] must be greater than the ideal, i.e., "
     909             :                                                  "100% thermal efficiency gas use rate of {:.2R} [W]",
     910           0 :                                                  NomCapVol,
     911             :                                                  NomPowerDes));
     912           0 :                         ShowContinueError(state,
     913             :                                           "Resize the Rated Gas Use Rate by dividing the ideal gas use rate with expected thermal efficiency. ");
     914             :                         // Changing this from a hard-stop condition to just a limiting condition of eta=1.0
     915             :                         // ErrorsFound = true;
     916           0 :                         ThermalEffRated = 1.0;
     917             :                     }
     918             :                 } else {
     919           1 :                     if (ThermalEffRated > 0.0) {
     920           1 :                         NominalPower = NominalPower / ThermalEffRated;
     921             :                     }
     922             :                 }
     923             : 
     924             :                 // gas fired steam humidifier's nominal gas use rate is always autosized
     925           1 :                 IsAutoSize = true;
     926             :             }
     927             : 
     928          38 :             NomPowerDes = NominalPower;
     929          38 :             if (IsAutoSize) {
     930           4 :                 NomPower = NomPowerDes;
     931          12 :                 BaseSizer::reportSizerOutput(
     932           8 :                     state, format(HumidifierType[static_cast<int>(HumType)]), Name, "Design Size Rated Power [W]", NomPowerDes);
     933             :             } else {
     934          34 :                 if (NomPower >= 0.0 && NomCap > 0.0) {
     935          34 :                     NomPowerUser = NomPower;
     936         102 :                     BaseSizer::reportSizerOutput(state,
     937          68 :                                                  format(HumidifierType[static_cast<int>(HumType)]),
     938             :                                                  Name,
     939             :                                                  "Design Size Rated Power [W]",
     940             :                                                  NomPowerDes,
     941             :                                                  "User-Specified Rated Power [W]",
     942             :                                                  NomPowerUser);
     943          34 :                     if (state.dataGlobal->DisplayExtraWarnings) {
     944           0 :                         if ((std::abs(NomPowerDes - NomPowerUser) / NomPowerUser) > state.dataSize->AutoVsHardSizingThreshold) {
     945           0 :                             ShowMessage(state,
     946           0 :                                         format("SizeHumidifier: Potential issue with equipment sizing for {} =\"{}\".",
     947           0 :                                                format(HumidifierType[static_cast<int>(HumType)]),
     948           0 :                                                Name));
     949           0 :                             ShowContinueError(state, format("User-Specified Rated Power of {:.2R} [W]", NomPowerUser));
     950           0 :                             ShowContinueError(state, format("differs from Design Size Rated Power of {:.2R} [W]", NomPowerDes));
     951           0 :                             ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
     952           0 :                             ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
     953             :                         }
     954             :                     }
     955          34 :                     if (NomPower < NominalPower) {
     956           0 :                         ShowWarningError(state,
     957           0 :                                          format(HumidifierType[static_cast<int>(HumType)]) +
     958           0 :                                              ": specified Rated Power is less than nominal Rated Power for " + ModuleObjectType +
     959           0 :                                              " steam humidifier = " + Name + ". ");
     960           0 :                         ShowContinueError(state, format(" specified Rated Power = {:.2R}", NomPower));
     961           0 :                         ShowContinueError(state, format(" while expecting a minimum Rated Power = {:.2R}", NominalPower));
     962             :                     }
     963             :                 } else {
     964           0 :                     ShowWarningError(state,
     965           0 :                                      format(HumidifierType[static_cast<int>(HumType)]) + ": specified nominal capacity is zero for " +
     966           0 :                                          ModuleObjectType + " steam humidifier = " + Name + ". ");
     967           0 :                     ShowContinueError(state, " For zero nominal capacity humidifier the rated power is zero.");
     968             :                 }
     969             :             }
     970             :         }
     971             : 
     972          38 :         if (ErrorsFound) {
     973           0 :             ShowFatalError(state,
     974           0 :                            format("{}: Mismatch was found in the Rated Gas Use Rate and Thermal Efficiency for gas fired steam humidifier = {}. ",
     975             :                                   CalledFrom,
     976           0 :                                   Name));
     977             :         }
     978          38 :     }
     979             : 
     980     1294540 :     void HumidifierData::ControlHumidifier(EnergyPlusData &state,
     981             :                                            Real64 &WaterAddNeeded // moisture addition rate needed to meet minimum humidity ratio setpoint [kg/s]
     982             :     )
     983             :     {
     984             : 
     985             :         // SUBROUTINE INFORMATION:
     986             :         //       AUTHOR         Fred Buhl
     987             :         //       DATE WRITTEN   September 2000
     988             :         //       MODIFIED       February 2015, B. Nigusse, FSEC, - transitioned the code to OO approach
     989             :         //       RE-ENGINEERED  na
     990             : 
     991             :         // PURPOSE OF THIS SUBROUTINE:
     992             :         // This subroutine sets the output required from the humidifier
     993             : 
     994             :         // METHODOLOGY EMPLOYED:
     995             :         // Uses a minimum humidity setpoint and water mass balance to calculate moisture addition needed
     996             : 
     997             :         // REFERENCES:
     998             :         // na
     999             : 
    1000             :         // Using/Aliasing
    1001             :         using Psychrometrics::PsyWFnTdbRhPb;
    1002             : 
    1003             :         // Locals
    1004             :         // SUBROUTINE ARGUMENT DEFINITIONS:
    1005             :         static constexpr std::string_view RoutineName("ControlHumidifier");
    1006             : 
    1007             :         // SUBROUTINE PARAMETER DEFINITIONS:
    1008             :         // na
    1009             : 
    1010             :         // INTERFACE BLOCK SPECIFICATIONS
    1011             :         // na
    1012             : 
    1013             :         // DERIVED TYPE DEFINITIONS
    1014             :         // na
    1015             : 
    1016             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1017             :         bool UnitOn;        // unit on flag
    1018             :         Real64 HumRatSatIn; // humidity ratio at saturation at the inlet temperature [kgWater/kgDryAir]
    1019             : 
    1020     1294540 :         UnitOn = true;
    1021     1294540 :         if (HumRatSet <= 0.0) UnitOn = false;
    1022     1294540 :         if (AirInMassFlowRate <= SmallMassFlow) UnitOn = false;
    1023     1294540 :         if (GetCurrentScheduleValue(state, SchedPtr) <= 0.0) UnitOn = false;
    1024     1294540 :         if (AirInHumRat >= HumRatSet) UnitOn = false;
    1025     1294540 :         HumRatSatIn = PsyWFnTdbRhPb(state, AirInTemp, 1.0, state.dataEnvrn->OutBaroPress, RoutineName);
    1026     1294540 :         if (AirInHumRat >= HumRatSatIn) UnitOn = false;
    1027     1294540 :         if (UnitOn) {
    1028             :             // AirMassFlowRate*AirInHumRat + WaterAddNeeded = AirMassFlowRate*HumRatSet
    1029      595808 :             WaterAddNeeded = AirInMassFlowRate * (HumRatSet - AirInHumRat);
    1030             :         } else {
    1031      698732 :             WaterAddNeeded = 0.0;
    1032             :         }
    1033     1294540 :     }
    1034             : 
    1035     1268393 :     void HumidifierData::CalcElecSteamHumidifier(EnergyPlusData &state, Real64 const WaterAddNeeded // moisture addition rate set by controller [kg/s]
    1036             :     )
    1037             :     {
    1038             : 
    1039             :         // SUBROUTINE INFORMATION:
    1040             :         //       AUTHOR         Fred Buhl
    1041             :         //       DATE WRITTEN   September 2000
    1042             :         //       MODIFIED       February 2015, B. Nigusse, FSEC, - transitioned the code to OO approach
    1043             :         //       RE-ENGINEERED  na
    1044             : 
    1045             :         // PURPOSE OF THIS SUBROUTINE:
    1046             :         // Calculate the electricity consumption and the outlet conditions for an electric steam
    1047             :         // humidifier, given the inlet conditions and the steam addition rate.
    1048             : 
    1049             :         // METHODOLOGY EMPLOYED:
    1050             :         // Uses energy and mass balance as well as pschrometric relations.
    1051             : 
    1052             :         // REFERENCES:
    1053             :         // ASHRAE HVAC 2 Toolkit, page 4-112
    1054             :         // 1997 ASHRAE Handbook Fundamentals, page 6.18
    1055             : 
    1056             :         // Using/Aliasing
    1057             :         using Psychrometrics::PsyHFnTdbW;
    1058             :         using Psychrometrics::PsyTdbFnHW;
    1059             :         using Psychrometrics::PsyWFnTdbRhPb;
    1060             :         using Psychrometrics::RhoH2O;
    1061             : 
    1062             :         // Locals
    1063             :         // SUBROUTINE ARGUMENT DEFINITIONS:
    1064             : 
    1065             :         // SUBROUTINE PARAMETER DEFINITIONS:
    1066             :         static constexpr std::string_view RoutineName("CalcElecSteamHumidifier");
    1067             : 
    1068             :         // INTERFACE BLOCK SPECIFICATIONS
    1069             :         // na
    1070             : 
    1071             :         // DERIVED TYPE DEFINITIONS
    1072             :         // na
    1073             : 
    1074             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1075             : 
    1076             :         Real64 HumRatSatOut;      // humidity ratio at saturation at the outlet temperature [kgWater/kgDryAir]
    1077             :         Real64 HumRatSatIn;       // humidity ratio at saturation at the inlet temperature [kgWater/kgDryAir]
    1078             :         Real64 WaterAddNeededMax; // moisture addition rate set by controller, limited by humidifier capacity
    1079             :         Real64 WaterInEnthalpy;   // enthalpy of the inlet steam [J/kg]
    1080             :         Real64 HumRatSatApp;      // the approximate humidity ratio where the line drawn between inlet and desired outlet conditions
    1081             :         // crosses the saturation line.
    1082             :         Real64 WaterDens; // density of liquid water [kg/m3]
    1083             : 
    1084     1268393 :         HumRatSatIn = PsyWFnTdbRhPb(state, AirInTemp, 1.0, state.dataEnvrn->OutBaroPress, RoutineName);
    1085     1268393 :         HumRatSatOut = 0.0;
    1086     1268393 :         HumRatSatApp = 0.0;
    1087     1268393 :         WaterInEnthalpy = 2676125.0; // At 100 C
    1088     1268393 :         WaterDens = RhoH2O(Constant::InitConvTemp);
    1089     1268393 :         WaterAddNeededMax = min(WaterAddNeeded, NomCap);
    1090     1268393 :         if (WaterAddNeededMax > 0.0) {
    1091             :             //   ma*W1 + mw = ma*W2
    1092             :             //   ma*h1 + mw*hw = ma*h2
    1093             :             // where ma is air mass flow rate; h1,W1 are the inlet enthalpy and humidity ratio; h2 and W2 are
    1094             :             // the outlet enthalpy and humidity ratio; mw is the steam mass flow rate; hw is the steam enthalpy.
    1095             :             // Setting mw equal to the desired water addition rate, use the above 2 equations to calculate the
    1096             :             // outlet conditions
    1097      590408 :             AirOutEnthalpy = (AirInMassFlowRate * AirInEnthalpy + WaterAddNeededMax * WaterInEnthalpy) / AirInMassFlowRate;
    1098      590408 :             AirOutHumRat = (AirInMassFlowRate * AirInHumRat + WaterAddNeededMax) / AirInMassFlowRate;
    1099      590408 :             AirOutTemp = PsyTdbFnHW(AirOutEnthalpy, AirOutHumRat);
    1100      590408 :             HumRatSatOut = PsyWFnTdbRhPb(state, AirOutTemp, 1.0, state.dataEnvrn->OutBaroPress, RoutineName);
    1101      590408 :             if (AirOutHumRat <= HumRatSatOut) {
    1102             :                 // If the outlet condition is below the saturation curve, the desired moisture addition rate can be met.
    1103      544584 :                 WaterAdd = WaterAddNeededMax;
    1104             :             } else {
    1105             :                 // The desired moisture addition rate results in an outlet state above the saturation curve. We need to
    1106             :                 // find the point where the line drawn between state 1 (inlet) and state 2 (our desired outlet) crosses
    1107             :                 // the saturation curve. This will be the new outlet condition. Rather than iterate to obtain this point,
    1108             :                 // we find it approximately by solving for the point where 2 lines cross: the first drawn from
    1109             :                 // state 1 to state 2, the second from T1, W1s to T2, W2s; where T1 is the inlet temperature, W1s is
    1110             :                 // the humidity ratio at saturation at temperature T1; and T2 is the desired outlet temperature, W2s
    1111             :                 // is the humidity ratio at saturation at temperature T2. The 2 lines are given by the equations:
    1112             :                 //   W = W1 + ((W2-W1)/(T2-T1))*(T-T1)
    1113             :                 //   W = W1s + ((W2s-W1s)/(T2-T1))*(T-T1)
    1114             :                 // Solving for the point where the line cross (T3,W3):
    1115             :                 //   W3 = W1 + ((W2-W1)*(W1s-W1))/(W2-W2s + W1s-W1)
    1116             :                 //   T3 = T1 + (W3-W1)*((T2-T1)/(W2-W1))  ! "T1 +" added by Shirey 8/12/04  That's correct! [WFB 9/29/2004]
    1117       45824 :                 HumRatSatApp = AirInHumRat +
    1118       45824 :                                (AirOutHumRat - AirInHumRat) * (HumRatSatIn - AirInHumRat) / (AirOutHumRat - HumRatSatOut + HumRatSatIn - AirInHumRat);
    1119       45824 :                 AirOutTemp = AirInTemp + (HumRatSatApp - AirInHumRat) * ((AirOutTemp - AirInTemp) / (AirOutHumRat - AirInHumRat));
    1120             :                 // This point isn't quite on the saturation curve since we made a linear approximation of the curve,
    1121             :                 // but the temperature should be very close to the correct outlet temperature. We will use this temperature
    1122             :                 // as the outlet temperature and move to the saturation curve for the outlet humidity and enthalpy
    1123       45824 :                 AirOutHumRat = PsyWFnTdbRhPb(state, AirOutTemp, 1.0, state.dataEnvrn->OutBaroPress, RoutineName);
    1124       45824 :                 AirOutEnthalpy = PsyHFnTdbW(AirOutTemp, AirOutHumRat);
    1125       45824 :                 WaterAdd = AirInMassFlowRate * (AirOutHumRat - AirInHumRat);
    1126             :             }
    1127             : 
    1128             :         } else {
    1129      677985 :             WaterAdd = 0.0;
    1130      677985 :             AirOutEnthalpy = AirInEnthalpy;
    1131      677985 :             AirOutTemp = AirInTemp;
    1132      677985 :             AirOutHumRat = AirInHumRat;
    1133             :         }
    1134     1268393 :         if (WaterAdd > 0.0) {
    1135      590408 :             ElecUseRate = (WaterAdd / NomCap) * NomPower + FanPower + StandbyPower;
    1136      677985 :         } else if (GetCurrentScheduleValue(state, SchedPtr) > 0.0) {
    1137      674829 :             ElecUseRate = StandbyPower;
    1138             :         } else {
    1139        3156 :             ElecUseRate = 0.0;
    1140             :         }
    1141     1268393 :         WaterConsRate = WaterAdd / WaterDens;
    1142     1268393 :         AirOutMassFlowRate = AirInMassFlowRate;
    1143     1268393 :     }
    1144             : 
    1145       26147 :     void HumidifierData::CalcGasSteamHumidifier(EnergyPlusData &state, Real64 const WaterAddNeeded // moisture addition rate set by controller [kg/s]
    1146             :     )
    1147             :     {
    1148             : 
    1149             :         // SUBROUTINE INFORMATION:
    1150             :         //       AUTHOR         Bereket Nigusse, FSEC/UCF
    1151             :         //       DATE WRITTEN   February 2015
    1152             :         //       MODIFIED       na
    1153             :         //       RE-ENGINEERED  na
    1154             : 
    1155             :         // PURPOSE OF THIS SUBROUTINE:
    1156             :         // Calculate the gas consumption and the outlet conditions for a gas fired steam
    1157             :         // humidifier, given the inlet conditions and the steam addition rate.
    1158             : 
    1159             :         // METHODOLOGY EMPLOYED:
    1160             :         // Uses energy and mass balance as well as pschrometric relations. Adopted
    1161             :         // from routine CalcElecSteamHumidifier by Fred Buhl
    1162             : 
    1163             :         // Using/Aliasing
    1164             :         using Curve::CurveValue;
    1165             :         using FluidProperties::GetSatEnthalpyRefrig;
    1166             :         using FluidProperties::GetSpecificHeatGlycol;
    1167             :         using Psychrometrics::PsyHFnTdbW;
    1168             :         using Psychrometrics::PsyTdbFnHW;
    1169             :         using Psychrometrics::PsyWFnTdbRhPb;
    1170             :         using Psychrometrics::RhoH2O;
    1171             : 
    1172             :         // SUBROUTINE PARAMETER DEFINITIONS:
    1173             :         static constexpr std::string_view RoutineName("CalcGasSteamHumidifier");
    1174       26147 :         Real64 constexpr TSteam(100.0); // saturated steam temperature generated by Humidifier [C]
    1175             : 
    1176             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1177             : 
    1178             :         Real64 HumRatSatOut;      // humidity ratio at saturation at the outlet temperature [kgWater/kgDryAir]
    1179             :         Real64 HumRatSatIn;       // humidity ratio at saturation at the inlet temperature [kgWater/kgDryAir]
    1180             :         Real64 WaterAddNeededMax; // moisture addition rate set by controller, limited by humidifier capacity
    1181             :         Real64 WaterInEnthalpy;   // enthalpy of the inlet steam [J/kg]
    1182             :         Real64 HumRatSatApp;      // the approximate humidity ratio where the line drawn between inlet and desired outlet conditions
    1183             :         // crosses the saturation line.
    1184             :         Real64 WaterDens;               // density of liquid water [kg/m3]
    1185       26147 :         Real64 ThermEffCurveOutput(0);  // thermal efficiency modifier normalized curve output value [-]
    1186             :         Real64 PartLoadRatio;           // gas fired humidifier part load ratio [-]
    1187       26147 :         Real64 GasUseRateAtRatedEff(0); // gas use rate at rated thermal efficiency [W]
    1188             :         Real64 WaterSpecHeatAvg;        // specific heat of water [J/kgK]
    1189             :         Real64 SteamSatEnthalpy;        // enthalpy of saturated steam at 100C [J/kg]
    1190             :         Real64 WaterSatEnthalpy;        // enthalpy of saturated water at 100C [J/kg]
    1191             :         Real64 Tref;                    // humidifier entering water temperature [C]
    1192             :         int RefrigerantIndex;           // refiferant index
    1193             :         int WaterIndex;                 // fluid type index
    1194             : 
    1195       26147 :         HumRatSatIn = PsyWFnTdbRhPb(state, AirInTemp, 1.0, state.dataEnvrn->OutBaroPress, RoutineName);
    1196       26147 :         HumRatSatOut = 0.0;
    1197       26147 :         HumRatSatApp = 0.0;
    1198       26147 :         WaterInEnthalpy = 2676125.0; // At 100 C
    1199       26147 :         WaterDens = RhoH2O(Constant::InitConvTemp);
    1200       26147 :         WaterAddNeededMax = min(WaterAddNeeded, NomCap);
    1201       26147 :         if (WaterAddNeededMax > 0.0) {
    1202             :             //   ma*W1 + mw = ma*W2
    1203             :             //   ma*h1 + mw*hw = ma*h2
    1204             :             // where ma is air mass flow rate; h1,W1 are the inlet enthalpy and humidity ratio; h2 and W2 are
    1205             :             // the outlet enthalpy and humidity ratio; mw is the steam mass flow rate; hw is the steam enthalpy.
    1206             :             // Setting mw equal to the desired water addition rate, use the above 2 equations to calculate the
    1207             :             // outlet conditions
    1208        5400 :             AirOutEnthalpy = (AirInMassFlowRate * AirInEnthalpy + WaterAddNeededMax * WaterInEnthalpy) / AirInMassFlowRate;
    1209        5400 :             AirOutHumRat = (AirInMassFlowRate * AirInHumRat + WaterAddNeededMax) / AirInMassFlowRate;
    1210        5400 :             AirOutTemp = PsyTdbFnHW(AirOutEnthalpy, AirOutHumRat);
    1211        5400 :             HumRatSatOut = PsyWFnTdbRhPb(state, AirOutTemp, 1.0, state.dataEnvrn->OutBaroPress, RoutineName);
    1212        5400 :             if (AirOutHumRat <= HumRatSatOut) {
    1213             :                 // If the outlet condition is below the saturation curve, the desired moisture addition rate can be met.
    1214        2506 :                 WaterAdd = WaterAddNeededMax;
    1215             :             } else {
    1216             :                 // The desired moisture addition rate results in an outlet state above the saturation curve. We need to
    1217             :                 // find the point where the line drawn between state 1 (inlet) and state 2 (our desired outlet) crosses
    1218             :                 // the saturation curve. This will be the new outlet condition. Rather than iterate to obtain this point,
    1219             :                 // we find it approximately by solving for the point where 2 lines cross: the first drawn from
    1220             :                 // state 1 to state 2, the second from T1, W1s to T2, W2s; where T1 is the inlet temperature, W1s is
    1221             :                 // the humidity ratio at saturation at temperature T1; and T2 is the desired outlet temperature, W2s
    1222             :                 // is the humidity ratio at saturation at temperature T2. The 2 lines are given by the equations:
    1223             :                 //   W = W1 + ((W2-W1)/(T2-T1))*(T-T1)
    1224             :                 //   W = W1s + ((W2s-W1s)/(T2-T1))*(T-T1)
    1225             :                 // Solving for the point where the line cross (T3,W3):
    1226             :                 //   W3 = W1 + ((W2-W1)*(W1s-W1))/(W2-W2s + W1s-W1)
    1227             :                 //   T3 = T1 + (W3-W1)*((T2-T1)/(W2-W1))  ! "T1 +" added by Shirey 8/12/04  That's correct! [WFB 9/29/2004]
    1228        2894 :                 HumRatSatApp = AirInHumRat +
    1229        2894 :                                (AirOutHumRat - AirInHumRat) * (HumRatSatIn - AirInHumRat) / (AirOutHumRat - HumRatSatOut + HumRatSatIn - AirInHumRat);
    1230        2894 :                 AirOutTemp = AirInTemp + (HumRatSatApp - AirInHumRat) * ((AirOutTemp - AirInTemp) / (AirOutHumRat - AirInHumRat));
    1231             :                 // This point isn't quite on the saturation curve since we made a linear approximation of the curve,
    1232             :                 // but the temperature should be very close to the correct outlet temperature. We will use this temperature
    1233             :                 // as the outlet temperature and move to the saturation curve for the outlet humidity and enthalpy
    1234        2894 :                 AirOutHumRat = PsyWFnTdbRhPb(state, AirOutTemp, 1.0, state.dataEnvrn->OutBaroPress, RoutineName);
    1235        2894 :                 AirOutEnthalpy = PsyHFnTdbW(AirOutTemp, AirOutHumRat);
    1236        2894 :                 WaterAdd = AirInMassFlowRate * (AirOutHumRat - AirInHumRat);
    1237             :             }
    1238             : 
    1239             :         } else {
    1240       20747 :             WaterAdd = 0.0;
    1241       20747 :             AirOutEnthalpy = AirInEnthalpy;
    1242       20747 :             AirOutTemp = AirInTemp;
    1243       20747 :             AirOutHumRat = AirInHumRat;
    1244             :         }
    1245       26147 :         if (WaterAdd > 0.0) {
    1246        5400 :             if (InletWaterTempOption == InletWaterTemp::Fixed) {
    1247        5400 :                 GasUseRateAtRatedEff = (WaterAdd / NomCap) * NomPower;
    1248           0 :             } else if (InletWaterTempOption == InletWaterTemp::Variable) {
    1249           0 :                 if (SuppliedByWaterSystem) { // use water use storage tank supply temperature
    1250           0 :                     CurMakeupWaterTemp = state.dataWaterData->WaterStorage(WaterTankID).TwaterSupply(TankSupplyID);
    1251             :                 } else { // use water main temperature
    1252           0 :                     CurMakeupWaterTemp = state.dataEnvrn->WaterMainsTemp;
    1253             :                 }
    1254           0 :                 Tref = CurMakeupWaterTemp;
    1255           0 :                 RefrigerantIndex = FluidProperties::GetRefrigNum(state, format(fluidNameSteam));
    1256           0 :                 WaterIndex = FluidProperties::GetGlycolNum(state, format(fluidNameWater));
    1257           0 :                 SteamSatEnthalpy = GetSatEnthalpyRefrig(state, format(fluidNameSteam), TSteam, 1.0, RefrigerantIndex, RoutineName);
    1258           0 :                 WaterSatEnthalpy = GetSatEnthalpyRefrig(state, format(fluidNameSteam), TSteam, 0.0, RefrigerantIndex, RoutineName);
    1259           0 :                 WaterSpecHeatAvg = 0.5 * (GetSpecificHeatGlycol(state, format(fluidNameWater), TSteam, WaterIndex, RoutineName) +
    1260           0 :                                           GetSpecificHeatGlycol(state, format(fluidNameWater), Tref, WaterIndex, RoutineName));
    1261           0 :                 GasUseRateAtRatedEff = WaterAdd * ((SteamSatEnthalpy - WaterSatEnthalpy) + WaterSpecHeatAvg * (TSteam - Tref)) / ThermalEffRated;
    1262             :             }
    1263        5400 :             PartLoadRatio = GasUseRateAtRatedEff / NomPower;
    1264        5400 :             if (EfficiencyCurvePtr > 0) { // calculate normalized thermal efficiency based on curve object type
    1265        5400 :                 ThermEffCurveOutput = CurveValue(state, EfficiencyCurvePtr, PartLoadRatio);
    1266             :             } else {
    1267           0 :                 ThermEffCurveOutput = 1.0;
    1268             :             }
    1269        5400 :             ThermalEff = ThermalEffRated * ThermEffCurveOutput;
    1270        5400 :             if (ThermEffCurveOutput != 0.0) {
    1271        5400 :                 GasUseRate = GasUseRateAtRatedEff / ThermEffCurveOutput;
    1272             :             }
    1273        5400 :             AuxElecUseRate = FanPower + StandbyPower;
    1274             : 
    1275       20747 :         } else if (GetCurrentScheduleValue(state, SchedPtr) > 0.0) {
    1276       20747 :             AuxElecUseRate = StandbyPower;
    1277             :         } else {
    1278           0 :             AuxElecUseRate = 0.0;
    1279             :         }
    1280       26147 :         WaterConsRate = WaterAdd / WaterDens;
    1281       26147 :         AirOutMassFlowRate = AirInMassFlowRate;
    1282       26147 :     }
    1283             : 
    1284     1294540 :     void HumidifierData::UpdateReportWaterSystem(EnergyPlusData &state) // number of the current humidifier being simulated
    1285             :     {
    1286             : 
    1287             :         // SUBROUTINE INFORMATION:
    1288             :         //       AUTHOR         B. Griffith
    1289             :         //       DATE WRITTEN   Aug. 2006
    1290             :         //       MODIFIED       na
    1291             :         //       RE-ENGINEERED  na
    1292             : 
    1293             :         // PURPOSE OF THIS SUBROUTINE:
    1294             :         // collect water system calculations , update and report them
    1295             : 
    1296             :         // Using/Aliasing
    1297     1294540 :         Real64 TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
    1298             : 
    1299             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1300             :         Real64 AvailTankVdot;
    1301             :         Real64 TankSupplyVdot;
    1302             :         Real64 StarvedVdot;
    1303             : 
    1304             :         // set demand request in WaterStorage if needed.
    1305     1294540 :         if (SuppliedByWaterSystem) {
    1306           0 :             state.dataWaterData->WaterStorage(WaterTankID).VdotRequestDemand(WaterTankDemandARRID) = WaterConsRate;
    1307             : 
    1308           0 :             AvailTankVdot =
    1309           0 :                 state.dataWaterData->WaterStorage(WaterTankID).VdotAvailDemand(WaterTankDemandARRID); // check what tank can currently provide
    1310             : 
    1311           0 :             StarvedVdot = 0.0;
    1312           0 :             TankSupplyVdot = WaterConsRate;                                                    // init
    1313           0 :             if ((AvailTankVdot < WaterConsRate) && (!(state.dataGlobal->BeginTimeStepFlag))) { // calculate starved flow
    1314           0 :                 StarvedVdot = WaterConsRate - AvailTankVdot;
    1315           0 :                 TankSupplyVdot = AvailTankVdot;
    1316             :             }
    1317             : 
    1318           0 :             TankSupplyVol = TankSupplyVdot * TimeStepSysSec;
    1319           0 :             StarvedSupplyVdot = StarvedVdot;
    1320           0 :             StarvedSupplyVol = StarvedVdot * TimeStepSysSec;
    1321             :         }
    1322     1294540 :     }
    1323             : 
    1324     1294540 :     void HumidifierData::UpdateHumidifier(EnergyPlusData &state) // number of the current humidifier being simulated
    1325             :     {
    1326             : 
    1327             :         // SUBROUTINE INFORMATION:
    1328             :         //       AUTHOR         Fred Buhl
    1329             :         //       DATE WRITTEN   September 2000
    1330             :         //       MODIFIED       na
    1331             :         //       RE-ENGINEERED  na
    1332             : 
    1333             :         // PURPOSE OF THIS SUBROUTINE:
    1334             :         // Moves humidifier output to the outlet nodes.
    1335             : 
    1336             :         // Set the outlet air node of the humidifier
    1337     1294540 :         state.dataLoopNodes->Node(AirOutNode).MassFlowRate = AirOutMassFlowRate;
    1338     1294540 :         state.dataLoopNodes->Node(AirOutNode).Temp = AirOutTemp;
    1339     1294540 :         state.dataLoopNodes->Node(AirOutNode).HumRat = AirOutHumRat;
    1340     1294540 :         state.dataLoopNodes->Node(AirOutNode).Enthalpy = AirOutEnthalpy;
    1341             : 
    1342             :         // Set the outlet nodes for properties that just pass through & not used
    1343     1294540 :         state.dataLoopNodes->Node(AirOutNode).Quality = state.dataLoopNodes->Node(AirInNode).Quality;
    1344     1294540 :         state.dataLoopNodes->Node(AirOutNode).Press = state.dataLoopNodes->Node(AirInNode).Press;
    1345     1294540 :         state.dataLoopNodes->Node(AirOutNode).MassFlowRateMin = state.dataLoopNodes->Node(AirInNode).MassFlowRateMin;
    1346     1294540 :         state.dataLoopNodes->Node(AirOutNode).MassFlowRateMax = state.dataLoopNodes->Node(AirInNode).MassFlowRateMax;
    1347     1294540 :         state.dataLoopNodes->Node(AirOutNode).MassFlowRateMinAvail = state.dataLoopNodes->Node(AirInNode).MassFlowRateMinAvail;
    1348     1294540 :         state.dataLoopNodes->Node(AirOutNode).MassFlowRateMaxAvail = state.dataLoopNodes->Node(AirInNode).MassFlowRateMaxAvail;
    1349             : 
    1350     1294540 :         if (state.dataContaminantBalance->Contaminant.CO2Simulation) {
    1351           0 :             state.dataLoopNodes->Node(AirOutNode).CO2 = state.dataLoopNodes->Node(AirInNode).CO2;
    1352             :         }
    1353     1294540 :         if (state.dataContaminantBalance->Contaminant.GenericContamSimulation) {
    1354           0 :             state.dataLoopNodes->Node(AirOutNode).GenContam = state.dataLoopNodes->Node(AirInNode).GenContam;
    1355             :         }
    1356     1294540 :     }
    1357             : 
    1358     1294540 :     void HumidifierData::ReportHumidifier(EnergyPlusData &state) // number of the current humidifier being simulated
    1359             :     {
    1360             : 
    1361             :         // SUBROUTINE INFORMATION:
    1362             :         //       AUTHOR         Fred Buhl
    1363             :         //       DATE WRITTEN   September 2000
    1364             :         //       MODIFIED       na
    1365             :         //       RE-ENGINEERED  na
    1366             : 
    1367             :         // PURPOSE OF THIS SUBROUTINE:
    1368             :         // Fill remaining report variables
    1369             : 
    1370             :         // Using/Aliasing
    1371     1294540 :         Real64 TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
    1372             : 
    1373     1294540 :         ElecUseEnergy = ElecUseRate * TimeStepSysSec;
    1374     1294540 :         WaterCons = WaterConsRate * TimeStepSysSec;
    1375     1294540 :         GasUseEnergy = GasUseRate * TimeStepSysSec;
    1376     1294540 :         AuxElecUseEnergy = AuxElecUseRate * TimeStepSysSec;
    1377     1294540 :     }
    1378             : 
    1379           0 :     int GetAirInletNodeNum(EnergyPlusData &state, std::string const &HumidifierName, bool &ErrorsFound)
    1380             :     {
    1381             :         // FUNCTION INFORMATION:
    1382             :         //       AUTHOR         Lixing Gu
    1383             :         //       DATE WRITTEN   May 2019
    1384             :         //       MODIFIED       na
    1385             :         //       RE-ENGINEERED  na
    1386             : 
    1387             :         // PURPOSE OF THIS FUNCTION:
    1388             :         // This function looks up the given humidifier and returns the air inlet node number.
    1389             :         // If incorrect humidifier name is given, ErrorsFound is returned as true and node number as zero.
    1390             : 
    1391             :         // Return value
    1392             :         int NodeNum; // node number returned
    1393             : 
    1394             :         // FUNCTION LOCAL VARIABLE DECLARATIONS:
    1395             :         int WhichHumidifier;
    1396             : 
    1397             :         // Obtains and Allocates heat exchanger related parameters from input file
    1398           0 :         if (state.dataHumidifiers->GetInputFlag) {
    1399           0 :             GetHumidifierInput(state);
    1400           0 :             state.dataHumidifiers->GetInputFlag = false;
    1401             :         }
    1402             : 
    1403           0 :         WhichHumidifier = Util::FindItemInList(HumidifierName, state.dataHumidifiers->Humidifier);
    1404           0 :         if (WhichHumidifier != 0) {
    1405           0 :             NodeNum = state.dataHumidifiers->Humidifier(WhichHumidifier).AirInNode;
    1406             :         } else {
    1407           0 :             ShowSevereError(state, format("GetAirInletNodeNum: Could not find Humidifier = \"{}\"", HumidifierName));
    1408           0 :             ErrorsFound = true;
    1409           0 :             NodeNum = 0;
    1410             :         }
    1411             : 
    1412           0 :         return NodeNum;
    1413             :     }
    1414             : 
    1415           0 :     int GetAirOutletNodeNum(EnergyPlusData &state, std::string const &HumidifierName, bool &ErrorsFound)
    1416             :     {
    1417             :         // PURPOSE OF THIS FUNCTION:
    1418             :         // This function looks up the given humidifier and returns the air outlet node number.
    1419             :         // If incorrect humidifier name is given, ErrorsFound is returned as true and node number as zero.
    1420             : 
    1421           0 :         if (state.dataHumidifiers->GetInputFlag) {
    1422           0 :             GetHumidifierInput(state);
    1423           0 :             state.dataHumidifiers->GetInputFlag = false;
    1424             :         }
    1425             : 
    1426           0 :         int WhichHumidifier = Util::FindItemInList(HumidifierName, state.dataHumidifiers->Humidifier);
    1427           0 :         if (WhichHumidifier != 0) {
    1428           0 :             return state.dataHumidifiers->Humidifier(WhichHumidifier).AirOutNode;
    1429             :         } else {
    1430           0 :             ShowSevereError(state, format("GetAirInletNodeNum: Could not find Humidifier = \"{}\"", HumidifierName));
    1431           0 :             ErrorsFound = true;
    1432           0 :             return 0;
    1433             :         }
    1434             :     }
    1435             : 
    1436             : } // namespace Humidifiers
    1437             : 
    1438             : } // namespace EnergyPlus

Generated by: LCOV version 1.14