LCOV - code coverage report
Current view: top level - EnergyPlus - Humidifiers.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 68.7 % 566 389
Test Date: 2025-06-02 07:23:51 Functions: 83.3 % 12 10

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

Generated by: LCOV version 2.0-1