LCOV - code coverage report
Current view: top level - EnergyPlus - HybridEvapCoolingModel.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 836 982 85.1 %
Date: 2024-08-23 23:50:59 Functions: 32 32 100.0 %

          Line data    Source code
       1             : // EnergyPlus, Copyright (c) 1996-2024, The Board of Trustees of the University of Illinois,
       2             : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
       3             : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
       4             : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
       5             : // contributors. All rights reserved.
       6             : //
       7             : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
       8             : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
       9             : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
      10             : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
      11             : // derivative works, and perform publicly and display publicly, and to permit others to do so.
      12             : //
      13             : // Redistribution and use in source and binary forms, with or without modification, are permitted
      14             : // provided that the following conditions are met:
      15             : //
      16             : // (1) Redistributions of source code must retain the above copyright notice, this list of
      17             : //     conditions and the following disclaimer.
      18             : //
      19             : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
      20             : //     conditions and the following disclaimer in the documentation and/or other materials
      21             : //     provided with the distribution.
      22             : //
      23             : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
      24             : //     the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
      25             : //     used to endorse or promote products derived from this software without specific prior
      26             : //     written permission.
      27             : //
      28             : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
      29             : //     without changes from the version obtained under this License, or (ii) Licensee makes a
      30             : //     reference solely to the software portion of its product, Licensee must refer to the
      31             : //     software as "EnergyPlus version X" software, where "X" is the version number Licensee
      32             : //     obtained under this License and may not use a different name for the software. Except as
      33             : //     specifically required in this Section (4), Licensee shall not use in a company name, a
      34             : //     product name, in advertising, publicity, or other promotional activities any name, trade
      35             : //     name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
      36             : //     similar designation, without the U.S. Department of Energy's prior written consent.
      37             : //
      38             : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
      39             : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
      40             : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
      41             : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      42             : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
      43             : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      44             : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
      45             : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      46             : // POSSIBILITY OF SUCH DAMAGE.
      47             : 
      48             : // C++ Headers
      49             : #include <cmath>
      50             : #include <string>
      51             : 
      52             : // ObjexxFCL Headers
      53             : #include <ObjexxFCL/Array.functions.hh>
      54             : #include <ObjexxFCL/Fmath.hh>
      55             : 
      56             : // EnergyPlus Headers
      57             : #include <EnergyPlus/CurveManager.hh>
      58             : #include <EnergyPlus/Data/EnergyPlusData.hh>
      59             : #include <EnergyPlus/DataEnvironment.hh>
      60             : #include <EnergyPlus/DataHVACGlobals.hh>
      61             : #include <EnergyPlus/General.hh>
      62             : #include <EnergyPlus/HybridEvapCoolingModel.hh>
      63             : #include <EnergyPlus/Psychrometrics.hh>
      64             : #include <EnergyPlus/ScheduleManager.hh>
      65             : #include <EnergyPlus/UtilityRoutines.hh>
      66             : 
      67             : namespace EnergyPlus { //***************
      68             : 
      69             : namespace HybridEvapCoolingModel {
      70             :     // Module containing the EvaporativeCoolers simulation routines
      71             : 
      72             :     // MODULE INFORMATION:
      73             :     //       AUTHOR         Spencer Dutton
      74             :     //       DATE WRITTEN   May 2017
      75             :     //       MODIFIED       na
      76             :     //       RE-ENGINEERED  na
      77             : 
      78             :     // PURPOSE OF THIS MODULE:
      79             :     // To encapsulate the data and algorithms required for the HybridUnitaryHVAC system.
      80             : 
      81             :     // METHODOLOGY EMPLOYED:
      82             :     // uses 6D lookup tables to provide performance data that describe 8 key performance metrics .
      83             : 
      84             :     // Supply Air Temperature, Supply Air Humidity Ratio, Electric Power, Supply Fan Electric Power, External Static Pressure
      85             :     // System Second Fuel Consumption, System Third Fuel Consumption, System Water Use
      86             : 
      87             :     // USE STATEMENTS:
      88             :     using namespace EnergyPlus::DataEnvironment;
      89             :     using namespace Psychrometrics;
      90             :     using Curve::CurveValue;
      91             :     using Curve::GetCurveIndex;
      92             :     using Curve::GetCurveMinMaxValues;
      93             :     using ScheduleManager::GetCurrentScheduleValue;
      94             : 
      95             : #define DEF_Tdb 0
      96             : #define DEF_RH 1
      97             : 
      98             : #define TEMP_CURVE 0
      99             : #define W_CURVE 1
     100             : #define POWER_CURVE 2
     101             : #define SUPPLY_FAN_POWER 3
     102             : #define EXTERNAL_STATIC_PRESSURE 4
     103             : #define SECOND_FUEL_USE 5
     104             : #define THIRD_FUEL_USE 6
     105             : #define WATER_USE 7
     106             : 
     107      114224 :     CMode::CMode()
     108      228448 :         : ModeID(0.0), Max_Msa(0.0), Min_Msa(0.0), Min_OAF(0.0), Max_OAF(0.0), Minimum_Outdoor_Air_Temperature(0.0),
     109      114224 :           Maximum_Outdoor_Air_Temperature(0.0), Minimum_Outdoor_Air_Humidity_Ratio(0.0), Maximum_Outdoor_Air_Humidity_Ratio(0.0),
     110      114224 :           ModelScalingFactor(0.0)
     111             :     {
     112      114224 :         MODE_BLOCK_OFFSET_Alpha = 9;
     113      114224 :         BLOCK_HEADER_OFFSET_Alpha = 20;
     114      114224 :         MODE1_BLOCK_OFFSET_Number = 2;
     115      114224 :         MODE_BLOCK_OFFSET_Number = 16;
     116      114224 :         BLOCK_HEADER_OFFSET_Number = 6;
     117      114224 :     }
     118             : 
     119           5 :     bool CMode::InitializeOutdoorAirTemperatureConstraints(Real64 min, Real64 max)
     120             :     {
     121             :         // note If this field is blank, there should be no lower constraint on outside air temperature
     122           5 :         Minimum_Outdoor_Air_Temperature = min;
     123           5 :         Maximum_Outdoor_Air_Temperature = max;
     124           5 :         return true;
     125             :     }
     126           5 :     bool CMode::InitializeOutdoorAirHumidityRatioConstraints(Real64 min, Real64 max)
     127             :     {
     128             :         // minimum 0.00 maximum 0.10, units kgWater / kgDryAir
     129             :         // note Mode0 will not be considerd when outside air absolute humidity is below the value in this field.
     130             :         // note If this field is blank, the lower constraint on outside air humidity ratio will be 0.00 kgWater / kgDryAir., default 0.00
     131             :         // the upper constraint on outside air humidity ratio will be 0.10 kgWater / kgDryAir, default 0.10
     132           5 :         Minimum_Outdoor_Air_Humidity_Ratio = min;
     133           5 :         Maximum_Outdoor_Air_Humidity_Ratio = max;
     134           5 :         return true;
     135             :     }
     136           5 :     bool CMode::InitializeOutdoorAirRelativeHumidityConstraints(Real64 min, Real64 max)
     137             :     {
     138             :         // minimum 0.00,maximum 100.00, units percent, Mode0 will not be considered when the outside air relative humidity is below the value in this
     139             :         // field.
     140             :         // note If this field is blank, the lower constraint on outside air relative humidity will be 0.00% (default 0.00), the upper constraint on
     141             :         // outside air relative humidity will be 100.00%, (default 100.00)
     142           5 :         Minimum_Outdoor_Air_Relative_Humidity = min;
     143           5 :         Maximum_Outdoor_Air_Relative_Humidity = max;
     144           5 :         return true;
     145             :     }
     146           5 :     bool CMode::InitializeReturnAirTemperatureConstraints(Real64 min, Real64 max)
     147             :     {
     148             :         // will not be considered when the return air temperature is below the value in this field.
     149             :         // If this field is blank, there will be no lower constraint on return air temperature
     150           5 :         Minimum_Return_Air_Temperature = min;
     151           5 :         Maximum_Return_Air_Temperature = max;
     152           5 :         return true;
     153             :     }
     154           5 :     bool CMode::InitializeReturnAirHumidityRatioConstraints(Real64 min, Real64 max)
     155             :     {
     156             :         // minimum 0.00 maximum 0.10, units kgWater / kgDryAir
     157             :         // note Mode0 will not be considerd when outside air absolute humidity is below the value in this field.
     158             :         // note If this field is blank, the lower constraint on outside air humidity ratio will be 0.00 kgWater / kgDryAir., default 0.00
     159             :         // the upper constraint on outside air humidity ratio will be 0.10 kgWater / kgDryAir, default 0.10
     160           5 :         Minimum_Return_Air_Humidity_Ratio = min;
     161           5 :         Maximum_Return_Air_Humidity_Ratio = max;
     162           5 :         return true;
     163             :     }
     164           5 :     bool CMode::InitializeReturnAirRelativeHumidityConstraints(Real64 min, Real64 max)
     165             :     {
     166             :         // minimum 0.00,maximum 100.00, units percent, Mode0 will not be considered when the outside air relative humidity is below the value in this
     167             :         // field.
     168             :         // note If this field is blank, the lower constraint on outside air relative humidity will be 0.00% (default 0.00), the upper constraint on
     169             :         // outside air relative humidity will be 100.00%, (default 100.00)
     170           5 :         Minimum_Return_Air_Relative_Humidity = min;
     171           5 :         Maximum_Return_Air_Relative_Humidity = max;
     172           5 :         return true;
     173             :     }
     174           5 :     bool CMode::InitializeOSAFConstraints(Real64 minOSAF, Real64 maxOSAF)
     175             :     {
     176             :         // minimum 0.00, maximum 1.00, Outdoor air fractions below this value will not be considered.
     177             :         // If this field is blank, the lower constraint on outside air fraction will be 0.00,default 0.10
     178           5 :         Min_OAF = minOSAF;
     179           5 :         Max_OAF = maxOSAF;
     180           5 :         return true;
     181             :     }
     182           5 :     bool CMode::InitializeMsaRatioConstraints(Real64 minMsa, Real64 maxMsa)
     183             :     {
     184             :         // minimum 0.00, maximum 1.00, Supply air mass flow rate ratios below this value will not be considered.
     185             :         // Supply air mass flow rate ratio describes supply air mass flow rate as a fraction of mass flow rate associated with the value in field :
     186             :         // "System Maximum Supply Air Flow Rate".  If this field is blank, the lower constraint on outside air fraction will be 0.00,default 0.10
     187           5 :         Min_Msa = minMsa;
     188           5 :         Max_Msa = maxMsa;
     189           5 :         return true;
     190             :     }
     191     1282389 :     bool CMode::ValidPointer(int curve_pointer)
     192             :     {
     193     1282389 :         if (curve_pointer >= 0)
     194     1060741 :             return true;
     195             :         else
     196      221648 :             return false;
     197             :     }
     198     1282389 :     Real64 CMode::CalculateCurveVal(EnergyPlusData &state, Real64 Tosa, Real64 Wosa, Real64 Tra, Real64 Wra, Real64 Msa, Real64 OSAF, int curveType)
     199             :     {
     200             :         // SUBROUTINE INFORMATION:
     201             :         //       AUTHOR         Spencer Maxwell Dutton
     202             :         //       DATE WRITTEN   October 2017
     203             :         //       MODIFIED
     204             :         //       RE-ENGINEERED  na
     205             : 
     206             :         // PURPOSE OF THIS SUBROUTINE:
     207             :         // Returns the normalized or scaled output from the performance curve as specified by curveType.  6 independent variables are required.
     208             : 
     209             :         // METHODOLOGY EMPLOYED:
     210             :         // Makes a call to the curve manager, then multiplies the result by either the by the ModelScalingFactor for extensive variables.
     211             :         // The ModelScalingFactor is the parent model's Scaling Factor, which is input by the user in the idf for this unit, and passed to
     212             :         // this CMode from the parent Model.
     213             :         // The following tables are for intensive variables : Supply Air Temperature, Supply Air Humidity, External Static Pressure
     214             :         // The following tables are for extensive variables : Electric Power, Fan Electric Power, Second Fuel Consumption,
     215             :         // Third Fuel Consumption, Water Use Lookup Table
     216             :         //
     217             :         // Tosa is the outside air temperature
     218             :         // Wosa is the outside humidity ratio
     219             :         // Tra return air temp
     220             :         // Wra return humidity ratio,
     221             :         // Msa supply air mass flow rate
     222             :         // OSAF outside air fraction
     223             : 
     224             :         // REFERENCES:
     225             :         // na
     226             : 
     227             :         // Using/Aliasing
     228     1282389 :         Real64 Y_val = 0;
     229             : 
     230     1282389 :         switch (curveType) {
     231      221180 :         case TEMP_CURVE:
     232      221180 :             if (ValidPointer(Tsa_curve_pointer)) {
     233      221180 :                 Y_val = CurveValue(state, Tsa_curve_pointer, Tosa, Wosa, Tra, Wra, Msa, OSAF);
     234             :             } else {
     235           0 :                 Y_val = Tra; // return air temp
     236             :             }
     237      221180 :             break;
     238             : 
     239      221180 :         case W_CURVE:
     240      221180 :             if (ValidPointer(HRsa_curve_pointer)) {
     241      221180 :                 Y_val = CurveValue(state, HRsa_curve_pointer, Tosa, Wosa, Tra, Wra, Msa, OSAF);
     242      221180 :                 Y_val = max(min(Y_val, 1.0), 0.0);
     243             :             } else {
     244           0 :                 Y_val = Wra; // return HR
     245             :             }
     246      221180 :             break;
     247             : 
     248             :         // The ModelScalingFactor factor for the Power, Fan Power, Water, and Fuel Use curves is equal to the Parent Model's Scaling Factor
     249      114204 :         case POWER_CURVE:
     250      114204 :             if (ValidPointer(Psa_curve_pointer)) {
     251      114204 :                 Y_val = ModelScalingFactor * CurveValue(state, Psa_curve_pointer, Tosa, Wosa, Tra, Wra, Msa, OSAF);
     252             :             } else {
     253           0 :                 Y_val = 0;
     254             :             }
     255      114204 :             break;
     256             : 
     257      322109 :         case SUPPLY_FAN_POWER:
     258      322109 :             if (ValidPointer(SFPsa_curve_pointer)) {
     259      322109 :                 Y_val = ModelScalingFactor * CurveValue(state, SFPsa_curve_pointer, Tosa, Wosa, Tra, Wra, Msa, OSAF);
     260             :             } else {
     261           0 :                 Y_val = 0;
     262             :             }
     263      322109 :             break;
     264             : 
     265      100929 :         case EXTERNAL_STATIC_PRESSURE:
     266      100929 :             if (ValidPointer(ESPsa_curve_pointer)) {
     267      100929 :                 Y_val = CurveValue(state, ESPsa_curve_pointer, Tosa, Wosa, Tra, Wra, Msa, OSAF);
     268             :             } else {
     269           0 :                 Y_val = 0; // or set a more reasonable default
     270             :             }
     271      100929 :             break;
     272             : 
     273      100929 :         case SECOND_FUEL_USE:
     274      100929 :             if (ValidPointer(SFUsa_curve_pointer)) {
     275       46017 :                 Y_val = ModelScalingFactor * CurveValue(state, SFUsa_curve_pointer, Tosa, Wosa, Tra, Wra, Msa, OSAF);
     276             :             } else {
     277       54912 :                 Y_val = 0; // or set a more reasonable default
     278             :             }
     279      100929 :             break;
     280             : 
     281      100929 :         case THIRD_FUEL_USE:
     282      100929 :             if (ValidPointer(TFUsa_curve_pointer)) {
     283           0 :                 Y_val = ModelScalingFactor * CurveValue(state, TFUsa_curve_pointer, Tosa, Wosa, Tra, Wra, Msa, OSAF);
     284             :             } else {
     285      100929 :                 Y_val = 0; // or set a more reasonable default
     286             :             }
     287      100929 :             break;
     288             : 
     289      100929 :         case WATER_USE:
     290      100929 :             if (ValidPointer(WUsa_curve_pointer)) {
     291       35122 :                 Y_val = ModelScalingFactor * CurveValue(state, WUsa_curve_pointer, Tosa, Wosa, Tra, Wra, Msa, OSAF);
     292             :             } else {
     293       65807 :                 Y_val = 0; // or set a more reasonable default
     294             :             }
     295      100929 :             break;
     296             : 
     297           0 :         default:
     298           0 :             break;
     299             :         }
     300             : 
     301     1282389 :         return Y_val;
     302             :     }
     303          48 :     void CMode::InitializeCurve(int curveType, int curve_ID)
     304             :     {
     305             :         // SUBROUTINE INFORMATION:
     306             :         //       AUTHOR         Spencer Maxwell Dutton
     307             :         //       DATE WRITTEN   October 2017
     308             :         //       MODIFIED
     309             :         //       RE-ENGINEERED  na
     310             : 
     311             :         // PURPOSE OF THIS SUBROUTINE:
     312             :         // Sets the curve ID assigned by the curve manager for the specific lookup Table, to a member variable.
     313             : 
     314             :         // METHODOLOGY EMPLOYED:
     315             :         //
     316             : 
     317             :         // REFERENCES:
     318             :         // na
     319             : 
     320             :         // Using/Aliasing
     321          48 :         switch (curveType) {
     322           6 :         case TEMP_CURVE:
     323           6 :             Tsa_curve_pointer = curve_ID;
     324           6 :             break;
     325           6 :         case W_CURVE:
     326           6 :             HRsa_curve_pointer = curve_ID;
     327           6 :             break;
     328           6 :         case POWER_CURVE:
     329           6 :             Psa_curve_pointer = curve_ID;
     330           6 :             break;
     331           6 :         case SUPPLY_FAN_POWER:
     332           6 :             SFPsa_curve_pointer = curve_ID;
     333           6 :             break;
     334           6 :         case EXTERNAL_STATIC_PRESSURE:
     335           6 :             ESPsa_curve_pointer = curve_ID;
     336           6 :             break;
     337           6 :         case SECOND_FUEL_USE:
     338           6 :             SFUsa_curve_pointer = curve_ID;
     339           6 :             break;
     340           6 :         case THIRD_FUEL_USE:
     341           6 :             TFUsa_curve_pointer = curve_ID;
     342           6 :             break;
     343           6 :         case WATER_USE:
     344           6 :             WUsa_curve_pointer = curve_ID;
     345           6 :             break;
     346           0 :         default:
     347           0 :             break;
     348             :         }
     349          48 :     }
     350             : 
     351           6 :     void CMode::GenerateSolutionSpace()
     352             :     {
     353             :         // SUBROUTINE INFORMATION:
     354             :         //       AUTHOR         Spencer Maxwell Dutton
     355             :         //       DATE WRITTEN   October 2017
     356             :         //       MODIFIED
     357             :         //       RE-ENGINEERED  na
     358             : 
     359             :         // PURPOSE OF THIS SUBROUTINE:
     360             :         // Generates a matrix of all possible combinations of OSAF and supply air mass flow rates.
     361             : 
     362             :         // METHODOLOGY EMPLOYED:
     363             :         // Calculate the range of supply air mass flow rate (SAMF) and OSAF the mode can operate under.
     364             :         // Calculate a step size to increment through the ranges of SAMF and OSAF, based on the ResolutionMsa and
     365             :         // ResolutionOSAs respectively (these are hard coded in the constructor, this is an important consideration
     366             :         // because the number of increments greatly effects the simulation run time).
     367             :         //
     368             :         // if the range is smaller than the minimum resolution,  then use the minimum resolution size as the minimum range over which to iterate
     369             :         // this should have the effect of keeping the number of solutions constant even if the range size varies.
     370             : 
     371             :         // REFERENCES:
     372             :         // na
     373             : 
     374             :         // Using/Aliasing
     375             : 
     376           6 :         if (Min_Msa == Max_Msa) {
     377           1 :             sol.MassFlowRatio.push_back(Max_Msa);
     378             :         } else {
     379           5 :             Real64 ResolutionMsa = (Max_Msa - Min_Msa) * 0.2;
     380          33 :             for (Real64 Msa_val = Max_Msa; Msa_val >= Min_Msa; Msa_val -= ResolutionMsa) {
     381          28 :                 sol.MassFlowRatio.push_back(Msa_val);
     382             :             }
     383             :         }
     384             : 
     385           6 :         if (Min_OAF == Max_OAF) {
     386           6 :             sol.OutdoorAirFraction.push_back(Max_OAF);
     387             :         } else {
     388           0 :             Real64 ResolutionOSA = (Max_OAF - Min_OAF) * 0.2;
     389           0 :             for (Real64 OAF_val = Max_OAF; OAF_val >= Min_OAF; OAF_val -= ResolutionOSA) {
     390           0 :                 sol.OutdoorAirFraction.push_back(OAF_val);
     391             :             }
     392             :         }
     393           6 :     }
     394             : 
     395           6 :     bool Model::ParseMode(EnergyPlusData &state,
     396             :                           Array1D_string Alphas,
     397             :                           Array1D_string cAlphaFields,
     398             :                           Array1D<Real64> Numbers,
     399             :                           Array1D_string cNumericFields,
     400             :                           Array1D<bool> lAlphaBlanks,
     401             :                           std::string cCurrentModuleObject)
     402             :     {
     403           6 :         CMode newMode;
     404           6 :         bool error = newMode.ParseMode(
     405             :             state, ModeCounter, &OperatingModes, ScalingFactor, Alphas, cAlphaFields, Numbers, cNumericFields, lAlphaBlanks, cCurrentModuleObject);
     406           6 :         ModeCounter++;
     407           6 :         return error;
     408           6 :     }
     409             : 
     410           6 :     bool CMode::ParseMode(EnergyPlusData &state,
     411             :                           int ModeCounter,
     412             :                           std::vector<CMode> *OperatingModes,
     413             :                           Real64 ScalingFactor,
     414             :                           Array1D_string Alphas,
     415             :                           Array1D_string cAlphaFields,
     416             :                           Array1D<Real64> Numbers,
     417             :                           Array1D_string cNumericFields,
     418             :                           Array1D<bool> lAlphaBlanks,
     419             :                           std::string cCurrentModuleObject)
     420             :     {
     421             :         // SUBROUTINE INFORMATION:
     422             :         //       AUTHOR         Spencer Maxwell Dutton
     423             :         //       DATE WRITTEN   October 2017
     424             :         //       MODIFIED
     425             :         //       RE-ENGINEERED  na
     426             : 
     427             :         // PURPOSE OF THIS SUBROUTINE:
     428             :         // Does the processing of each of the seperate modes
     429             : 
     430             :         // METHODOLOGY EMPLOYED:
     431             :         // As the number of modes defined in the idf is not known until its read in, this method uses two counters to keep track of the inputs in the
     432             :         // Alphas and Numbers arrays. Three constants are used, BLOCK_HEADER_OFFSET_Alpha, BLOCK_HEADER_OFFSET_Number and MODE1_BLOCK_OFFSET_Number
     433             :         // if ever additional input parameters are added to the idf these offset counters would have to be adjusted accordingly.
     434             : 
     435             :         // REFERENCES:
     436             :         // na
     437             : 
     438             :         // Using/Aliasing
     439           6 :         ModeID = ModeCounter;
     440           6 :         ModelScalingFactor = ScalingFactor;
     441             : 
     442             :         int inter_Number;
     443           6 :         bool ErrorsFound = false;
     444           6 :         int inter_Alpha = BLOCK_HEADER_OFFSET_Alpha + MODE_BLOCK_OFFSET_Alpha * ModeID;
     445           6 :         if (ModeID > 0) {
     446           5 :             inter_Number = BLOCK_HEADER_OFFSET_Number + MODE1_BLOCK_OFFSET_Number + MODE_BLOCK_OFFSET_Number * (ModeID - 1);
     447             :         } else {
     448           1 :             inter_Number = BLOCK_HEADER_OFFSET_Number + MODE1_BLOCK_OFFSET_Number;
     449             :         }
     450           6 :         std::ostringstream strs;
     451           6 :         strs << ModeID;
     452             : 
     453           6 :         int curveID = -1;
     454           6 :         if (lAlphaBlanks(inter_Alpha)) {
     455           0 :             ModeName = "Mode" + strs.str();
     456             :         } else {
     457           6 :             ModeName = Alphas(inter_Alpha);
     458             :         }
     459             : 
     460           6 :         curveID = -1;
     461           6 :         inter_Alpha = inter_Alpha + 1;
     462           6 :         if (lAlphaBlanks(inter_Alpha)) {
     463           1 :             InitializeCurve(TEMP_CURVE, curveID); // as this is invalid curve id CalculateCurveVal will return a default when called
     464             :         } else {
     465           5 :             curveID = GetCurveIndex(state, Alphas(inter_Alpha));
     466           5 :             if (curveID == 0) {
     467           0 :                 ShowSevereError(state, format("Invalid {}={}", cAlphaFields(inter_Alpha), Alphas(inter_Alpha)));
     468           0 :                 ShowContinueError(state, format("Entered in {}", cCurrentModuleObject));
     469           0 :                 ErrorsFound = true;
     470           0 :                 InitializeCurve(TEMP_CURVE, -1);
     471             :             } else {
     472           5 :                 InitializeCurve(TEMP_CURVE, curveID);
     473             :             }
     474             :         }
     475             : 
     476           6 :         inter_Alpha = inter_Alpha + 1;
     477             : 
     478             :         // A22, \field Mode0 Supply Air Humidity Ratio Lookup Table Name
     479           6 :         curveID = -1;
     480           6 :         if (lAlphaBlanks(inter_Alpha)) {
     481           1 :             InitializeCurve(W_CURVE, curveID); // as this is invalid curve id CalculateCurveVal will return a default  when called
     482             :         } else {
     483           5 :             curveID = GetCurveIndex(state, Alphas(inter_Alpha));
     484           5 :             if (curveID == 0) {
     485           0 :                 ShowSevereError(state, format("Invalid {}={}", cAlphaFields(inter_Alpha), Alphas(inter_Alpha)));
     486           0 :                 ShowContinueError(state, format("Entered in {}", cCurrentModuleObject));
     487           0 :                 ErrorsFound = true;
     488           0 :                 InitializeCurve(W_CURVE, -1);
     489             :             } else {
     490           5 :                 InitializeCurve(W_CURVE, curveID);
     491             :             }
     492             :         }
     493           6 :         inter_Alpha = inter_Alpha + 1;
     494             :         // A23, \field Mode0 System Electric Power Lookup Table Name
     495           6 :         curveID = -1;
     496           6 :         if (lAlphaBlanks(inter_Alpha)) {
     497           0 :             InitializeCurve(POWER_CURVE, curveID); // as this is invalid curve id CalculateCurveVal will return a default
     498             :         } else {
     499           6 :             curveID = GetCurveIndex(state, Alphas(inter_Alpha));
     500           6 :             if (curveID == 0) {
     501           0 :                 ShowSevereError(state, format("Invalid {}={}", cAlphaFields(inter_Alpha), Alphas(inter_Alpha)));
     502           0 :                 ShowContinueError(state, format("Entered in {}", cCurrentModuleObject));
     503           0 :                 ErrorsFound = true;
     504           0 :                 InitializeCurve(POWER_CURVE, -1);
     505             :             } else {
     506           6 :                 InitializeCurve(POWER_CURVE, curveID);
     507             :             }
     508             :         }
     509             :         // A24, \field Mode0 Supply Fan Electric Power Lookup Table Name
     510           6 :         inter_Alpha = inter_Alpha + 1;
     511           6 :         curveID = -1;
     512           6 :         if (lAlphaBlanks(inter_Alpha)) {
     513           1 :             InitializeCurve(SUPPLY_FAN_POWER, curveID); // as this is invalid curve id CalculateCurveVal will return a default
     514             :         } else {
     515           5 :             curveID = GetCurveIndex(state, Alphas(inter_Alpha));
     516           5 :             if (curveID == 0) {
     517           0 :                 ShowSevereError(state, format("Invalid {}={}", cAlphaFields(inter_Alpha), Alphas(inter_Alpha)));
     518           0 :                 ShowContinueError(state, format("Entered in {}", cCurrentModuleObject));
     519           0 :                 ErrorsFound = true;
     520           0 :                 InitializeCurve(SUPPLY_FAN_POWER, -1);
     521             :             } else {
     522           5 :                 InitializeCurve(SUPPLY_FAN_POWER, curveID);
     523             :             }
     524             :         }
     525             :         // A25, \field Mode0 External Static Pressure Lookup Table Name
     526           6 :         inter_Alpha = inter_Alpha + 1;
     527           6 :         curveID = -1;
     528           6 :         if (lAlphaBlanks(inter_Alpha)) {
     529           1 :             InitializeCurve(EXTERNAL_STATIC_PRESSURE, curveID); // as this is invalid curve id CalculateCurveVal will return a default
     530             :         } else {
     531           5 :             curveID = GetCurveIndex(state, Alphas(inter_Alpha));
     532           5 :             if (curveID == 0) {
     533           0 :                 ShowSevereError(state, format("Invalid {}={}", cAlphaFields(inter_Alpha), Alphas(inter_Alpha)));
     534           0 :                 ShowContinueError(state, format("Entered in {}", cCurrentModuleObject));
     535           0 :                 ErrorsFound = true;
     536           0 :                 InitializeCurve(EXTERNAL_STATIC_PRESSURE, -1);
     537             :             } else {
     538           5 :                 InitializeCurve(EXTERNAL_STATIC_PRESSURE, curveID);
     539             :             }
     540             :         }
     541             :         //
     542             :         // A26, \field Mode0 System Second Fuel Consumption Lookup Table Nam
     543           6 :         inter_Alpha = inter_Alpha + 1;
     544           6 :         curveID = -1;
     545           6 :         if (lAlphaBlanks(inter_Alpha)) {
     546           5 :             InitializeCurve(SECOND_FUEL_USE, curveID); // as this is invalid curve id CalculateCurveVal will return a default
     547             :         } else {
     548           1 :             curveID = GetCurveIndex(state, Alphas(inter_Alpha));
     549           1 :             if (curveID == 0) {
     550           0 :                 ShowSevereError(state, format("Invalid {}={}", cAlphaFields(inter_Alpha), Alphas(inter_Alpha)));
     551           0 :                 ShowContinueError(state, format("Entered in {}", cCurrentModuleObject));
     552           0 :                 ErrorsFound = true;
     553           0 :                 InitializeCurve(SECOND_FUEL_USE, -1);
     554             :             } else {
     555           1 :                 InitializeCurve(SECOND_FUEL_USE, curveID);
     556             :             }
     557             :         }
     558             :         // A27, \field Mode0 System Third Fuel Consumption Lookup Table Name
     559           6 :         inter_Alpha = inter_Alpha + 1;
     560           6 :         curveID = -1;
     561           6 :         if (lAlphaBlanks(inter_Alpha)) {
     562           6 :             InitializeCurve(THIRD_FUEL_USE, curveID); // as this is invalid curve id CalculateCurveVal will return a default
     563             :         } else {
     564           0 :             curveID = GetCurveIndex(state, Alphas(inter_Alpha));
     565           0 :             if (curveID == 0) {
     566           0 :                 ShowSevereError(state, format("Invalid {}={}", cAlphaFields(inter_Alpha), Alphas(inter_Alpha)));
     567           0 :                 ShowContinueError(state, format("Entered in {}", cCurrentModuleObject));
     568           0 :                 ErrorsFound = true;
     569           0 :                 InitializeCurve(THIRD_FUEL_USE, -1);
     570             :             } else {
     571           0 :                 InitializeCurve(THIRD_FUEL_USE, curveID);
     572             :             }
     573             :         }
     574             :         // A28, \field Mode0 System Water Use Lookup Table Name
     575           6 :         inter_Alpha = inter_Alpha + 1;
     576           6 :         curveID = -1;
     577           6 :         if (lAlphaBlanks(inter_Alpha)) {
     578           3 :             InitializeCurve(WATER_USE, curveID); // as this is invalid curve id CalculateCurveVal will return a default
     579             :         } else {
     580           3 :             curveID = GetCurveIndex(state, Alphas(inter_Alpha));
     581           3 :             if (curveID == 0) {
     582           0 :                 ShowSevereError(state, format("Invalid {}={}", cAlphaFields(inter_Alpha), Alphas(inter_Alpha)));
     583           0 :                 ShowContinueError(state, format("Entered in {}", cCurrentModuleObject));
     584           0 :                 ErrorsFound = true;
     585           0 :                 InitializeCurve(WATER_USE, -1);
     586             :             } else {
     587           3 :                 InitializeCurve(WATER_USE, curveID);
     588             :             }
     589             :         }
     590           6 :         if (ModeID == 0) {
     591           1 :             (*OperatingModes).push_back(*this);
     592           1 :             return ErrorsFound;
     593             :         }
     594             :         // N8, \field Mode1  Minimum Outdoor Air Temperature
     595             :         // N9, \field Mode1  Maximum Outdoor Air Temperature
     596           5 :         bool ok = InitializeOutdoorAirTemperatureConstraints(Numbers(inter_Number), Numbers(inter_Number + 1));
     597           5 :         if (!ok) {
     598           0 :             ShowSevereError(state, format("Invalid {}Or Invalid{}", cNumericFields(inter_Number), cNumericFields(inter_Number + 1)));
     599           0 :             ShowContinueError(state, format("Entered in {}", cCurrentModuleObject));
     600           0 :             ErrorsFound = true;
     601             :         }
     602           5 :         inter_Number = inter_Number + 2;
     603             :         // N10, \field Mode1  Minimum Outdoor Air Humidity Ratio
     604             :         // N11, \field Mode1  Maximum Outdoor Air Humidity Ratio
     605           5 :         ok = InitializeOutdoorAirHumidityRatioConstraints(Numbers(inter_Number), Numbers(inter_Number + 1));
     606           5 :         if (!ok) {
     607           0 :             ShowSevereError(state, format("Invalid {}Or Invalid{}", cNumericFields(inter_Number), cNumericFields(inter_Number + 1)));
     608           0 :             ShowContinueError(state, format("Entered in {}", cCurrentModuleObject));
     609           0 :             ErrorsFound = true;
     610             :         }
     611           5 :         inter_Number = inter_Number + 2;
     612             :         // N12, \field Mode1 Minimum Outdoor Air Relative Humidity
     613             :         // N13, \field Mode1 Maximum Outdoor Air Relative Humidity
     614           5 :         ok = InitializeOutdoorAirRelativeHumidityConstraints(Numbers(inter_Number), Numbers(inter_Number + 1));
     615           5 :         if (!ok) {
     616           0 :             ShowSevereError(state, format("Invalid {}Or Invalid{}", cNumericFields(inter_Number), cNumericFields(inter_Number + 1)));
     617           0 :             ShowContinueError(state, format("Entered in {}", cCurrentModuleObject));
     618           0 :             ErrorsFound = true;
     619             :         }
     620           5 :         inter_Number = inter_Number + 2;
     621             :         // N14, \field Mode1 Minimum Return Air Temperature
     622             :         // N15, \field Mode1 Maximum Return Air Temperature
     623           5 :         ok = InitializeReturnAirTemperatureConstraints(Numbers(inter_Number), Numbers(inter_Number + 1));
     624           5 :         if (!ok) {
     625           0 :             ShowSevereError(state, format("Invalid {}Or Invalid{}", cNumericFields(inter_Number), cNumericFields(inter_Number + 1)));
     626           0 :             ShowContinueError(state, format("Entered in {}", cCurrentModuleObject));
     627           0 :             ErrorsFound = true;
     628             :         }
     629           5 :         inter_Number = inter_Number + 2;
     630             :         // N16, \field Mode1 Minimum Return Air Humidity Ratio
     631             :         // N17, \field Mode1 Maximum Return Air Humidity Ratio
     632           5 :         ok = InitializeReturnAirHumidityRatioConstraints(Numbers(inter_Number), Numbers(inter_Number + 1));
     633           5 :         if (!ok) {
     634           0 :             ShowSevereError(state, format("Invalid {}Or Invalid{}", cNumericFields(inter_Number), cNumericFields(inter_Number + 1)));
     635           0 :             ShowContinueError(state, format("Entered in {}", cCurrentModuleObject));
     636           0 :             ErrorsFound = true;
     637             :         }
     638           5 :         inter_Number = inter_Number + 2;
     639             :         // N18, \field Mode1 Minimum Return Air Relative HumidityInitialize
     640             :         // N19, \field Mode1 Maximum Return Air Relative Humidity
     641           5 :         ok = InitializeReturnAirRelativeHumidityConstraints(Numbers(inter_Number), Numbers(inter_Number + 1));
     642           5 :         if (!ok) {
     643           0 :             ShowSevereError(state,
     644           0 :                             format("Invalid {}={}Or Invalid{}={}",
     645             :                                    cAlphaFields(inter_Number),
     646             :                                    Alphas(inter_Number),
     647             :                                    cAlphaFields(inter_Number + 1),
     648             :                                    Alphas(inter_Number + 1)));
     649           0 :             ShowContinueError(state, format("Entered in {}", cCurrentModuleObject));
     650           0 :             ErrorsFound = true;
     651             :         }
     652           5 :         inter_Number = inter_Number + 2;
     653             :         // N20, \field Mode1 Minimum Outdoor Air Fraction
     654             :         // N21, \field Mode1 Maximum Outdoor Air Fraction
     655             : 
     656           5 :         ok = InitializeOSAFConstraints(Numbers(inter_Number), Numbers(inter_Number + 1));
     657           5 :         if (!ok) {
     658           0 :             ShowSevereError(state, format("Error in OSAFConstraints{}through{}", cAlphaFields(inter_Number), cAlphaFields(inter_Number + 1)));
     659           0 :             ShowContinueError(state, format("Entered in {}", cCurrentModuleObject));
     660           0 :             ErrorsFound = true;
     661             :         }
     662             :         // N22, \field Mode1 Minimum Supply Air Mass Flow Rate Ratio
     663             :         // N23, \field Mode1 Maximum Supply Air Mass Flow Rate Ratio
     664           5 :         inter_Number = inter_Number + 2;
     665           5 :         ok = InitializeMsaRatioConstraints(Numbers(inter_Number), Numbers(inter_Number + 1));
     666           5 :         if (!ok) {
     667           0 :             ShowSevereError(state, format("Error in OSAFConstraints{}through{}", cAlphaFields(inter_Number), cAlphaFields(inter_Number + 1)));
     668           0 :             ShowContinueError(state, format("Entered in {}", cCurrentModuleObject));
     669           0 :             ErrorsFound = true;
     670             :         }
     671           5 :         (*OperatingModes).push_back(*this);
     672           5 :         return ErrorsFound;
     673           6 :     }
     674             : 
     675       66085 :     bool CMode::MeetsOAEnvConstraints(Real64 Tosa, Real64 Wosa, Real64 RHosa)
     676             :     {
     677             :         // SUBROUTINE INFORMATION:
     678             :         //       AUTHOR         Spencer Maxwell Dutton
     679             :         //       DATE WRITTEN   October 2017
     680             :         //       MODIFIED
     681             :         //       RE-ENGINEERED  na
     682             : 
     683             :         // PURPOSE OF THIS SUBROUTINE:
     684             :         // To check to see if this mode of operation is able to operate given the specified outdoor environmental conditions.
     685             : 
     686             :         // METHODOLOGY EMPLOYED:
     687             :         // Constraining certain modes to only operate over certain environmental conditions gives the user greater control in which
     688             :         // modes the algorithm selects.
     689             : 
     690             :         // REFERENCES:
     691             :         // na
     692             : 
     693             :         // Using/Aliasing
     694       66085 :         bool OATempConstraintmet = false;
     695       66085 :         bool OAHRConstraintmet = false;
     696       66085 :         bool OARHConstraintmet = false;
     697             : 
     698       66085 :         if (Tosa >= Minimum_Outdoor_Air_Temperature && Tosa <= Maximum_Outdoor_Air_Temperature) {
     699       66085 :             OATempConstraintmet = true;
     700             :         }
     701             : 
     702       66085 :         if (Wosa >= Minimum_Outdoor_Air_Humidity_Ratio && Wosa <= Maximum_Outdoor_Air_Humidity_Ratio) {
     703       66085 :             OAHRConstraintmet = true;
     704             :         }
     705             : 
     706       66085 :         if (RHosa >= Minimum_Outdoor_Air_Relative_Humidity && RHosa <= Maximum_Outdoor_Air_Relative_Humidity) {
     707       66085 :             OARHConstraintmet = true;
     708             :         }
     709       66085 :         if (OATempConstraintmet && OAHRConstraintmet && OARHConstraintmet) {
     710       66085 :             return true;
     711             :         } else {
     712           0 :             return false;
     713             :         }
     714             :     }
     715             : 
     716      221180 :     bool Model::MeetsSupplyAirTOC(EnergyPlusData &state, Real64 Tsupplyair)
     717             :     {
     718             :         // SUBROUTINE INFORMATION:
     719             :         //       AUTHOR         Spencer Maxwell Dutton
     720             :         //       DATE WRITTEN   October 2017
     721             :         //       MODIFIED
     722             :         //       RE-ENGINEERED  na
     723             : 
     724             :         // PURPOSE OF THIS SUBROUTINE:
     725             :         // To check to see if this this particular setting (combination of mode, OSAF and Msa) meets the required minumum
     726             :         // supply air temperature specified in the schedules
     727             : 
     728             :         // METHODOLOGY EMPLOYED:
     729             :         // Checks the minimum and maximum supply air temperatures and tests to see if the proposed supply air temperature is in the acceptable range.
     730             : 
     731             :         // REFERENCES:
     732             :         // na
     733             : 
     734             :         // Using/Aliasing
     735      221180 :         Real64 MinSAT = 10;
     736      221180 :         Real64 MaxSAT = 20;
     737      221180 :         if (TsaMin_schedule_pointer > 0) {
     738      221180 :             MinSAT = GetCurrentScheduleValue(state, TsaMin_schedule_pointer);
     739             :         }
     740      221180 :         if (TsaMax_schedule_pointer > 0) {
     741      221180 :             MaxSAT = GetCurrentScheduleValue(state, TsaMax_schedule_pointer);
     742             :         }
     743      221180 :         if (Tsupplyair < MinSAT || Tsupplyair > MaxSAT) return false;
     744      100929 :         return true;
     745             :     }
     746             : 
     747      221180 :     bool Model::MeetsSupplyAirRHOC(EnergyPlusData &state, Real64 SupplyW)
     748             :     {
     749             :         // SUBROUTINE INFORMATION:
     750             :         //       AUTHOR         Spencer Maxwell Dutton
     751             :         //       DATE WRITTEN   October 2017
     752             :         //       MODIFIED
     753             :         //       RE-ENGINEERED  na
     754             : 
     755             :         // PURPOSE OF THIS SUBROUTINE:
     756             :         // To check to see if this this particular setting (combination of mode, OSAF and Msa) meets the required minumum
     757             :         // supply air relative humidity specified in the schedules
     758             : 
     759             :         // METHODOLOGY EMPLOYED:
     760             :         // Checks the scheduled minimum and maximum supply air RH and tests to see if the proposed supply air RH is in the acceptable range.
     761             : 
     762             :         // REFERENCES:
     763             :         // na
     764             : 
     765             :         // Using/Aliasing
     766      221180 :         Real64 MinRH = 0;
     767      221180 :         Real64 MaxRH = 1;
     768      221180 :         if (RHsaMin_schedule_pointer > 0) {
     769      221180 :             MinRH = GetCurrentScheduleValue(state, RHsaMin_schedule_pointer);
     770             :         }
     771      221180 :         if (RHsaMax_schedule_pointer > 0) {
     772      221180 :             MaxRH = GetCurrentScheduleValue(state, RHsaMax_schedule_pointer);
     773             :         }
     774      221180 :         if (SupplyW < MinRH || SupplyW > MaxRH) return false;
     775      221180 :         return true;
     776             :     }
     777             : 
     778           2 :     Model::Model()
     779           6 :         : Initialized(false), ZoneNum(0), SchedPtr(0), SystemMaximumSupplyAirFlowRate(0.0), ScalingFactor(0.0),
     780           2 :           ScaledSystemMaximumSupplyAirMassFlowRate(0.0), UnitOn(0), UnitTotalCoolingRate(0.0), UnitTotalCoolingEnergy(0.0),
     781           2 :           UnitSensibleCoolingRate(0.0), UnitSensibleCoolingEnergy(0.0), UnitLatentCoolingRate(0.0), UnitLatentCoolingEnergy(0.0),
     782           2 :           SystemTotalCoolingRate(0.0), SystemTotalCoolingEnergy(0.0), SystemSensibleCoolingRate(0.0), SystemSensibleCoolingEnergy(0.0),
     783           2 :           SystemLatentCoolingRate(0.0), SystemLatentCoolingEnergy(0.0), UnitTotalHeatingRate(0.0), UnitTotalHeatingEnergy(0.0),
     784           2 :           UnitSensibleHeatingRate(0.0), UnitSensibleHeatingEnergy(0.0), UnitLatentHeatingRate(0.0), UnitLatentHeatingEnergy(0.0),
     785           2 :           SystemTotalHeatingRate(0.0), SystemTotalHeatingEnergy(0.0), SystemSensibleHeatingRate(0.0), SystemSensibleHeatingEnergy(0.0),
     786           2 :           SystemLatentHeatingRate(0.0), SystemLatentHeatingEnergy(0.0), SupplyFanElectricPower(0.0), SupplyFanElectricEnergy(0.0),
     787           2 :           SecondaryFuelConsumptionRate(0.0), SecondaryFuelConsumption(0.0), ThirdFuelConsumptionRate(0.0), ThirdFuelConsumption(0.0),
     788           2 :           WaterConsumptionRate(0.0), WaterConsumption(0.0), QSensZoneOut(0), QLatentZoneOut(0), QLatentZoneOutMass(0), ExternalStaticPressure(0.0),
     789           2 :           RequestedHumdificationMass(0.0), RequestedHumdificationLoad(0.0), RequestedHumdificationEnergy(0.0), RequestedDeHumdificationMass(0.0),
     790           2 :           RequestedDeHumdificationLoad(0.0), RequestedDeHumdificationEnergy(0.0), RequestedLoadToHeatingSetpoint(0.0),
     791           2 :           RequestedLoadToCoolingSetpoint(0.0), TsaMin_schedule_pointer(0), TsaMax_schedule_pointer(0), RHsaMin_schedule_pointer(0),
     792           2 :           RHsaMax_schedule_pointer(0), PrimaryMode(0), PrimaryModeRuntimeFraction(0.0), averageOSAF(0), ErrorCode(0), InletNode(0), OutletNode(0),
     793           2 :           SecondaryInletNode(0), SecondaryOutletNode(0), FinalElectricalPower(0.0), FinalElectricalEnergy(0.0), InletMassFlowRate(0.0),
     794           2 :           InletTemp(0.0), InletWetBulbTemp(0.0), InletHumRat(0.0), InletEnthalpy(0.0), InletPressure(0.0), InletRH(0.0),
     795           2 :           OutletVolumetricFlowRate(0.0), OutletMassFlowRate(0.0), PowerLossToAir(0.0), FanHeatTemp(0.0), OutletTemp(0.0), OutletWetBulbTemp(0.0),
     796           2 :           OutletHumRat(0.0), OutletEnthalpy(0.0), OutletPressure(0.0), OutletRH(0.0), SecInletMassFlowRate(0.0), SecInletTemp(0.0),
     797           2 :           SecInletWetBulbTemp(0.0), SecInletHumRat(0.0), SecInletEnthalpy(0.0), SecInletPressure(0.0), SecInletRH(0.0), SecOutletMassFlowRate(0.0),
     798           2 :           SecOutletTemp(0.0), SecOutletWetBulbTemp(0.0), SecOutletHumRat(0.0), SecOutletEnthalpy(0.0), SecOutletPressure(0.0), SecOutletRH(0.0),
     799           2 :           Wsa(0.0), SupplyVentilationAir(0.0), SupplyVentilationVolume(0.0), OutdoorAir(false), MinOA_Msa(0.0), OARequirementsPtr(0), Tsa(0.0),
     800           2 :           ModeCounter(0), CoolingRequested(false), HeatingRequested(false), VentilationRequested(false), DehumidificationRequested(false),
     801           2 :           HumidificationRequested(false)
     802             :     {
     803           2 :         WarnOnceFlag = false;
     804           2 :         count_EnvironmentConditionsMetOnce = 0;
     805           2 :         count_EnvironmentConditionsNotMet = 0;
     806           2 :         count_SAHR_OC_MetOnce = 0;
     807           2 :         count_SAT_OC_MetOnce = 0;
     808           2 :         count_DidWeMeetLoad = 0;
     809           2 :         count_DidWeNotMeetLoad = 0;
     810             :         // vector below used store the modes in each timestep that don't meet humidity or temperature limits, used in warnings
     811           2 :         std::vector<int> temp(25);
     812           2 :         SAT_OC_MetinMode_v = temp;
     813           2 :         SAHR_OC_MetinMode_v = temp;
     814             : 
     815           2 :         ModeCounter = 0;
     816             : 
     817           2 :         CurrentOperatingSettings.resize(5);
     818             : 
     819           2 :         InitializeModelParams();
     820           2 :     }
     821             : 
     822       26552 :     void Model::ResetOutputs()
     823             :     {
     824       26552 :         UnitTotalCoolingRate = 0;
     825       26552 :         UnitTotalCoolingEnergy = 0;
     826       26552 :         UnitSensibleCoolingRate = 0;
     827       26552 :         UnitSensibleCoolingEnergy = 0;
     828       26552 :         UnitLatentCoolingRate = 0;
     829       26552 :         UnitLatentCoolingEnergy = 0;
     830       26552 :         SystemTotalCoolingRate = 0;
     831       26552 :         SystemTotalCoolingEnergy = 0;
     832       26552 :         SystemSensibleCoolingRate = 0;
     833       26552 :         SystemSensibleCoolingEnergy = 0;
     834       26552 :         SystemLatentCoolingRate = 0;
     835       26552 :         SystemLatentCoolingEnergy = 0;
     836       26552 :         UnitTotalHeatingRate = 0;
     837       26552 :         UnitTotalHeatingEnergy = 0;
     838       26552 :         UnitSensibleHeatingRate = 0;
     839       26552 :         UnitSensibleHeatingEnergy = 0;
     840       26552 :         UnitLatentHeatingRate = 0;
     841       26552 :         UnitLatentHeatingEnergy = 0;
     842       26552 :         SystemTotalHeatingRate = 0;
     843       26552 :         SystemTotalHeatingEnergy = 0;
     844       26552 :         SystemSensibleHeatingRate = 0;
     845       26552 :         SystemSensibleHeatingEnergy = 0;
     846       26552 :         SystemLatentHeatingRate = 0;
     847       26552 :         SystemLatentHeatingEnergy = 0;
     848       26552 :         SupplyFanElectricPower = 0;
     849       26552 :         SupplyFanElectricEnergy = 0;
     850       26552 :         SecondaryFuelConsumptionRate = 0;
     851       26552 :         SecondaryFuelConsumption = 0;
     852       26552 :         ThirdFuelConsumptionRate = 0;
     853       26552 :         ThirdFuelConsumption = 0;
     854       26552 :         WaterConsumptionRate = 0;
     855       26552 :         WaterConsumption = 0;
     856       26552 :         ExternalStaticPressure = 0;
     857       26552 :     }
     858             : 
     859       13277 :     void Model::InitializeModelParams()
     860             :     {
     861             :         // SUBROUTINE INFORMATION:
     862             :         //       AUTHOR         Spencer Maxwell Dutton
     863             :         //       DATE WRITTEN   October 2017
     864             :         //       MODIFIED
     865             :         //       RE-ENGINEERED  na
     866             : 
     867             :         // PURPOSE OF THIS SUBROUTINE:
     868             :         // Reset calculation values
     869             : 
     870             :         // METHODOLOGY EMPLOYED:
     871             :         //
     872             : 
     873             :         // REFERENCES:
     874             :         // na
     875             : 
     876             :         // Using/Aliasing
     877       13277 :         ResetOutputs();
     878       13277 :         PrimaryMode = 0;
     879       13277 :         PrimaryModeRuntimeFraction = 0;
     880       13277 :         optimal_EnvCondMet = false;
     881       13277 :         Tsa = 0;
     882             :         // reset the power use to a high value, this is replaced during the calculation keeping the "best" setting.
     883             : 
     884       13277 :         RunningPeakCapacity_EnvCondMet = false;
     885       13277 :         Settings.clear();
     886       13277 :     }
     887             : 
     888           1 :     void Model::Initialize(int ZoneNumber)
     889             :     {
     890             :         // SUBROUTINE INFORMATION:
     891             :         //       AUTHOR         Spencer Maxwell Dutton
     892             :         //       DATE WRITTEN   October 2017
     893             :         //       MODIFIED
     894             :         //       RE-ENGINEERED  na
     895             : 
     896             :         // PURPOSE OF THIS SUBROUTINE:
     897             :         // Specify solution space resolution, and populate the solution spaces in each mode
     898             : 
     899             :         // METHODOLOGY EMPLOYED:
     900             :         // Solution spaces are the matrices of possible settings settings (combination of OSA fraction and supply air mass flow rate)
     901             :         // This method calls the GenerateSolutionSpace for each of the modes defined in the idf.
     902             :         // REFERENCES:
     903             :         // na
     904             : 
     905             :         // Using/Aliasing
     906             : 
     907           1 :         ZoneNum = ZoneNumber;
     908           1 :         if (Initialized) {
     909           0 :             return;
     910             :         }
     911           1 :         Initialized = true;
     912             : 
     913             :         // Iterate through modes of operation generating a matrix of OSAF and Msa to test in the algorithm.
     914           7 :         for (auto &thisOperatingMode : OperatingModes) {
     915           6 :             thisOperatingMode.GenerateSolutionSpace();
     916           1 :         }
     917             : 
     918           1 :         Initialized = true;
     919             :     }
     920             : 
     921      114204 :     Real64 Model::CheckVal_W(EnergyPlusData &state, Real64 W, Real64 T, Real64 P)
     922             :     {
     923             :         // P must be in pascals NOT kPa
     924      114204 :         Real64 OutletRHtest = PsyRhFnTdbWPb(state, T, W, P); // could also use outlet pressure instead of fixed
     925             :         Real64 OutletW =
     926      114204 :             PsyWFnTdbRhPb(state, T, OutletRHtest, P, "Humidity ratio exceeded realistic range error called in " + Name + ", check performance curve");
     927      114204 :         return OutletW;
     928             :     }
     929       13275 :     Real64 Model::CheckVal_T(EnergyPlusData &state, Real64 T)
     930             :     {
     931       13275 :         if ((T > 100) || (T < 0)) {
     932           2 :             ShowWarningError(state, format("Supply air temperature exceeded realistic range error called in {}, check performance curve", Name));
     933             :         }
     934       13275 :         return T;
     935             :     }
     936       13275 :     bool Model::SetStandByMode(EnergyPlusData &state, CMode Mode0, Real64 Tosa, Real64 Wosa, Real64 Tra, Real64 Wra)
     937             :     {
     938             :         // SUBROUTINE INFORMATION:
     939             :         //       AUTHOR         Spencer Maxwell Dutton
     940             :         //       DATE WRITTEN   October 2017
     941             :         //       MODIFIED
     942             :         //       RE-ENGINEERED  na
     943             : 
     944             :         // PURPOSE OF THIS SUBROUTINE:
     945             :         // Set the supply air mass flow rate, power use, and all the other parameters for a setting.
     946             : 
     947             :         // METHODOLOGY EMPLOYED:
     948             :         // Uses the relevant lookup take to specify the parameters, or uses default conditions.
     949             :         // In setting the supply air temperature for now just use return air future improvement will use look up table
     950             : 
     951             :         // REFERENCES:
     952             :         // na
     953             : 
     954             :         // if the map of the solution space looks valid then populate the class member oStandBy (CSetting) with the settings data (what OSAF it runs
     955             :         // at, and how much power it uses etc.
     956       13275 :         if (Mode0.sol.MassFlowRatio.size() > 0) {
     957       13275 :             Real64 MsaRatio = Mode0.sol.MassFlowRatio[0];
     958       13275 :             Real64 OSAF = Mode0.sol.OutdoorAirFraction[0];
     959             : 
     960       13275 :             oStandBy.ScaledSupply_Air_Mass_Flow_Rate = MsaRatio * ScaledSystemMaximumSupplyAirMassFlowRate;
     961       13275 :             oStandBy.Unscaled_Supply_Air_Mass_Flow_Rate = oStandBy.ScaledSupply_Air_Mass_Flow_Rate / ScalingFactor;
     962       13275 :             oStandBy.ScaledSupply_Air_Ventilation_Volume = MsaRatio * ScaledSystemMaximumSupplyAirMassFlowRate / state.dataEnvrn->StdRhoAir;
     963       13275 :             oStandBy.Supply_Air_Mass_Flow_Rate_Ratio = MsaRatio;
     964       13275 :             oStandBy.ElectricalPower =
     965       13275 :                 Mode0.CalculateCurveVal(state, Tosa, Wosa, Tra, Wra, oStandBy.Unscaled_Supply_Air_Mass_Flow_Rate, OSAF, POWER_CURVE);
     966       13275 :             oStandBy.Outdoor_Air_Fraction = OSAF;
     967       13275 :             oStandBy.SupplyAirTemperature = Tra;
     968       13275 :             oStandBy.SupplyAirW = Wra;
     969       13275 :             oStandBy.Mode = 0;
     970       13275 :             oStandBy.Mixed_Air_Temperature = Tra;
     971       13275 :             oStandBy.Mixed_Air_W = Wra;
     972             :         } else {
     973             :             // if the solution space is invalid return true that an error occurred.
     974           0 :             return true;
     975             :         }
     976             : 
     977       13275 :         return false;
     978             :     }
     979             : 
     980      159300 :     Real64 Model::CalculateTimeStepAverage(SYSTEMOUTPUTS val)
     981             :     {
     982             :         // SUBROUTINE INFORMATION:
     983             :         //       AUTHOR         Spencer Maxwell Dutton
     984             :         //       DATE WRITTEN   October 2017
     985             :         //       MODIFIED
     986             :         //       RE-ENGINEERED  na
     987             : 
     988             :         // PURPOSE OF THIS SUBROUTINE:
     989             :         // Calculates the resultant supply air conditions when the system operates in
     990             :         // multiple settings within a timestep.
     991             : 
     992             :         // METHODOLOGY EMPLOYED:
     993             :         // For longer simulation timesteps this model can consider partial runtime fractions
     994             :         // operating in different settings for a fraction of the total simulation time step reducing the likelyhood of over conditioning.
     995             :         // Intensive variables that do not depend on system size (like temperature, pressure,etc), and extensive variables (variable whose values
     996             :         // depend on the quantity of substance) are handled differently
     997             :         //
     998             :         // Extensive variables ( Mass Flow, Volume flow, Fuel use etc), are averaged weighted by the amount of time spent in each setting.
     999             :         // for example if then system operates for 25% of the time with a mass flow of 4kg/s, and 75% of the time at a mass flow of 0kg/s then the
    1000             :         // resultant time step average mass flow rate would be  1 kg/s.
    1001             : 
    1002             :         // Intensive values in each part runtime fraction are first multiplied by the Scaled Supply Air Mass Flow Rate for each setting
    1003             :         // and then once all the various runtime fractions are added up, the resultant is divided by the overal time step average Scaled Supply Air
    1004             :         // Mass Flow Rate
    1005             :         //
    1006             :         // REFERENCES:
    1007             :         // na
    1008             : 
    1009             :         // Using/Aliasing
    1010      159300 :         Real64 averagedVal = 0;
    1011      159300 :         Real64 MassFlowDependentDenominator = 0;
    1012      159300 :         Real64 value = 0;
    1013             : 
    1014      955800 :         for (auto &thisOperatingSettings : CurrentOperatingSettings) {
    1015      796500 :             switch (val) {
    1016       66375 :             case SYSTEMOUTPUTS::VENTILATION_AIR_V:
    1017       66375 :                 value = thisOperatingSettings.ScaledSupply_Air_Ventilation_Volume;
    1018       66375 :                 break;
    1019       66375 :             case SYSTEMOUTPUTS::SYSTEM_FUEL_USE:
    1020       66375 :                 value = thisOperatingSettings.ElectricalPower;
    1021       66375 :                 break;
    1022       66375 :             case SYSTEMOUTPUTS::OSUPPLY_FAN_POWER:
    1023       66375 :                 value = thisOperatingSettings.SupplyFanElectricPower;
    1024       66375 :                 break;
    1025       66375 :             case SYSTEMOUTPUTS::OSECOND_FUEL_USE:
    1026       66375 :                 value = thisOperatingSettings.SecondaryFuelConsumptionRate;
    1027       66375 :                 break;
    1028       66375 :             case SYSTEMOUTPUTS::OTHIRD_FUEL_USE:
    1029       66375 :                 value = thisOperatingSettings.ThirdFuelConsumptionRate;
    1030       66375 :                 break;
    1031       66375 :             case SYSTEMOUTPUTS::OEXTERNAL_STATIC_PRESSURE:
    1032       66375 :                 value = thisOperatingSettings.ExternalStaticPressure * thisOperatingSettings.ScaledSupply_Air_Mass_Flow_Rate;
    1033       66375 :                 break;
    1034       66375 :             case SYSTEMOUTPUTS::OWATER_USE:
    1035       66375 :                 value = thisOperatingSettings.WaterConsumptionRate;
    1036       66375 :                 break;
    1037       66375 :             case SYSTEMOUTPUTS::SUPPLY_AIR_TEMP:
    1038       66375 :                 value = thisOperatingSettings.SupplyAirTemperature * thisOperatingSettings.ScaledSupply_Air_Mass_Flow_Rate;
    1039       66375 :                 break;
    1040       66375 :             case SYSTEMOUTPUTS::MIXED_AIR_TEMP:
    1041       66375 :                 value = thisOperatingSettings.Mixed_Air_Temperature * thisOperatingSettings.ScaledSupply_Air_Mass_Flow_Rate;
    1042       66375 :                 break;
    1043       66375 :             case SYSTEMOUTPUTS::SUPPLY_MASS_FLOW:
    1044       66375 :                 value = thisOperatingSettings.ScaledSupply_Air_Mass_Flow_Rate;
    1045       66375 :                 break;
    1046       66375 :             case SYSTEMOUTPUTS::SUPPLY_AIR_HR:
    1047       66375 :                 value = thisOperatingSettings.SupplyAirW * thisOperatingSettings.ScaledSupply_Air_Mass_Flow_Rate;
    1048       66375 :                 break;
    1049       66375 :             case SYSTEMOUTPUTS::MIXED_AIR_HR:
    1050       66375 :                 value = thisOperatingSettings.Mixed_Air_W * thisOperatingSettings.ScaledSupply_Air_Mass_Flow_Rate;
    1051       66375 :                 break;
    1052           0 :             default:
    1053           0 :                 assert(false);
    1054             :             }
    1055      796500 :             Real64 part_run = thisOperatingSettings.Runtime_Fraction;
    1056      796500 :             averagedVal = averagedVal + value * part_run;
    1057      796500 :             MassFlowDependentDenominator = thisOperatingSettings.ScaledSupply_Air_Mass_Flow_Rate * part_run + MassFlowDependentDenominator;
    1058      159300 :         }
    1059             : 
    1060      159300 :         CSetting StandbyMode = (*(CurrentOperatingSettings.begin()));
    1061      159300 :         switch (val) {
    1062       13275 :         case SYSTEMOUTPUTS::SUPPLY_AIR_TEMP:
    1063       13275 :             if (MassFlowDependentDenominator == 0) {
    1064        7740 :                 averagedVal = StandbyMode.SupplyAirTemperature;
    1065             :             } else {
    1066        5535 :                 averagedVal = averagedVal / MassFlowDependentDenominator;
    1067             :             }
    1068       13275 :             break;
    1069       13275 :         case SYSTEMOUTPUTS::OEXTERNAL_STATIC_PRESSURE:
    1070       13275 :             if (MassFlowDependentDenominator == 0) {
    1071        7740 :                 averagedVal = StandbyMode.ExternalStaticPressure;
    1072             :             } else {
    1073        5535 :                 averagedVal = averagedVal / MassFlowDependentDenominator;
    1074             :             }
    1075       13275 :             break;
    1076       13275 :         case SYSTEMOUTPUTS::SUPPLY_AIR_HR:
    1077       13275 :             if (MassFlowDependentDenominator == 0) {
    1078        7740 :                 averagedVal = StandbyMode.SupplyAirW;
    1079             :             } else {
    1080        5535 :                 averagedVal = averagedVal / MassFlowDependentDenominator;
    1081             :             }
    1082       13275 :             break;
    1083       13275 :         case SYSTEMOUTPUTS::MIXED_AIR_TEMP:
    1084       13275 :             if (MassFlowDependentDenominator == 0) {
    1085        7740 :                 averagedVal = StandbyMode.Mixed_Air_Temperature;
    1086             :             } else {
    1087        5535 :                 averagedVal = averagedVal / MassFlowDependentDenominator;
    1088             :             }
    1089       13275 :             break;
    1090       13275 :         case SYSTEMOUTPUTS::MIXED_AIR_HR:
    1091       13275 :             if (MassFlowDependentDenominator == 0) {
    1092        7740 :                 averagedVal = StandbyMode.Mixed_Air_W;
    1093             :             } else {
    1094        5535 :                 averagedVal = averagedVal / MassFlowDependentDenominator;
    1095             :             }
    1096       13275 :             break;
    1097       92925 :         default:
    1098       92925 :             break;
    1099             :         }
    1100      318600 :         return averagedVal;
    1101             :     }
    1102             : 
    1103      100929 :     Real64 Model::CalculatePartRuntimeFraction(Real64 MinOA_Msa,
    1104             :                                                Real64 Mvent,
    1105             :                                                Real64 RequestedCoolingLoad,
    1106             :                                                Real64 RequestedHeatingLoad,
    1107             :                                                Real64 SensibleRoomORZone,
    1108             :                                                Real64 RequestedDehumidificationLoad,
    1109             :                                                Real64 RequestedMoistureLoad,
    1110             :                                                Real64 LatentRoomORZone)
    1111             :     {
    1112             :         // SUBROUTINE INFORMATION:
    1113             :         //       AUTHOR         Spencer Maxwell Dutton
    1114             :         //       DATE WRITTEN   October 2017
    1115             :         //       MODIFIED
    1116             :         //       RE-ENGINEERED  na
    1117             : 
    1118             :         // PURPOSE OF THIS SUBROUTINE:
    1119             :         // Calculates the minimum runtime fraction in a given setting needed to meet the
    1120             :         // sensible cooling, sensible heating, dehumidification and humidification loads
    1121             :         // and ventilation loads.
    1122             : 
    1123             :         // METHODOLOGY EMPLOYED:
    1124             :         // Calculate the minimum runtime fractions for each load that needs to be met and find the lowest of those runtime fractions.
    1125             :         // Go through each of the requirements (ventilation, heating, cooling, dehumidification, humidification and work out what the minimum runtime
    1126             :         // fraction you would need in order to meet all these requirements. Importantly the SensibleRoomORZone is either (-) for heating or (+) for
    1127             :         // cooling, where as the RequestedCoolingLoad and RequestedHeatingLoad, are both positive (never below 0).
    1128             : 
    1129             :         // REFERENCES:
    1130             :         // na
    1131             : 
    1132             :         // Using/Aliasing
    1133             :         Real64 PLHumidRatio, PLDehumidRatio, PLVentRatio, PLSensibleCoolingRatio, PLSensibleHeatingRatio, PartRuntimeFraction;
    1134      100929 :         PLHumidRatio = PLDehumidRatio = PLVentRatio = PLSensibleCoolingRatio = PLSensibleHeatingRatio = 0;
    1135             : 
    1136      100929 :         if (Mvent > 0) {
    1137      100929 :             PLVentRatio = MinOA_Msa / Mvent;
    1138             :         }
    1139      100929 :         PartRuntimeFraction = PLVentRatio;
    1140             : 
    1141      100929 :         if (SensibleRoomORZone > 0) {
    1142       67087 :             PLSensibleCoolingRatio = std::abs(RequestedCoolingLoad) / std::abs(SensibleRoomORZone);
    1143             :         }
    1144      100929 :         if (PLSensibleCoolingRatio > PartRuntimeFraction) {
    1145       40465 :             PartRuntimeFraction = PLSensibleCoolingRatio;
    1146             :         }
    1147             : 
    1148      100929 :         if (SensibleRoomORZone < 0) {
    1149       33842 :             PLSensibleHeatingRatio = std::abs(RequestedHeatingLoad) / std::abs(SensibleRoomORZone);
    1150             :         }
    1151             : 
    1152      100929 :         if (PLSensibleHeatingRatio > PartRuntimeFraction) {
    1153       17310 :             PartRuntimeFraction = PLSensibleHeatingRatio;
    1154             :         }
    1155             : 
    1156      100929 :         if (RequestedDehumidificationLoad > 0) {
    1157        3326 :             PLDehumidRatio = std::abs(RequestedDehumidificationLoad) / std::abs(LatentRoomORZone);
    1158             :         }
    1159             : 
    1160      100929 :         if (PLDehumidRatio > PartRuntimeFraction) {
    1161        3318 :             PartRuntimeFraction = PLDehumidRatio;
    1162             :         }
    1163             : 
    1164      100929 :         if (RequestedMoistureLoad > 0) {
    1165       97595 :             PLHumidRatio = std::abs(RequestedMoistureLoad) / std::abs(LatentRoomORZone);
    1166             :         }
    1167      100929 :         if (PLHumidRatio > PartRuntimeFraction) {
    1168       94885 :             PartRuntimeFraction = PLHumidRatio;
    1169             :         }
    1170             : 
    1171      100929 :         if (PartRuntimeFraction < 0) {
    1172           0 :             PartRuntimeFraction = 0;
    1173             :         }
    1174      100929 :         if (PartRuntimeFraction > 1) {
    1175       93249 :             PartRuntimeFraction = 1;
    1176             :         }
    1177             : 
    1178      100929 :         return PartRuntimeFraction;
    1179             :     }
    1180             : 
    1181       13217 :     int Model::SetOperatingSetting(EnergyPlusData &state, CStepInputs StepIns)
    1182             :     {
    1183             :         // SUBROUTINE INFORMATION:
    1184             :         //       AUTHOR         Spencer Dutton
    1185             :         //       DATE WRITTEN   May 2017
    1186             :         //       MODIFIED       na
    1187             :         //       RE-ENGINEERED  na
    1188             : 
    1189             :         // PURPOSE OF THIS SUBROUTINE:
    1190             :         // This subroutine determines the set of operating settings for the HybridUniaryHVAC
    1191             :         // It is called from Model::doStep, the main calculation step
    1192             :         // at the system time step.
    1193             : 
    1194             :         // METHODOLOGY EMPLOYED:
    1195             :         // 1) Clear out the set of operating settings from the previous time step.
    1196             :         // 2) Iterate through each operating mode and weed out modes that are not intended to operate in current environmental conditions.
    1197             :         //        -> For each mode that is viable iterate thought the solution space and identify settings that meet the ventilation
    1198             :         // requirements
    1199             :         //      -> settings that do are stored in the a container (Settings)
    1200             :         // 3) Iterate through all the settings in Settings
    1201             :         //
    1202             :         // 4) Calculate the setting zone sensible cooling and heating load and humidifcation and dehumidifcation.
    1203             :         // 5) Test to see if conditioning and humidification loads are met.
    1204             :         // 6) Calculate setting power consumption, use the setting delivered ventilation and loads to calculate the
    1205             :         // 7) minimum runtime fraction needed to meet those loads, then assuming that part runtime fraction calculate the setting part run time power
    1206             :         // use. 8)   If the setting meets both the conditioning and humidification loads then test to see if its optimal in terms of energy use.
    1207             :         //          ->if so, save that setting as the current optimal.
    1208             :         //          ->if not ignore it.
    1209             :         //      If the setting failed ot meet either the conditioning or humidification loads, then
    1210             :         //      -> firstly check to see if no previous other setting (in this calculation step) has met both the load and humidification requirements
    1211             :         //              -> if so
    1212             :         //                  -> check if this setting meets the conditioning load (only)
    1213             :         //                      -> if so
    1214             :         //                          ->check to see if this setting is better at meeting the dehumidification or humidification lad
    1215             :         //  than any previous setting this step.
    1216             :         //                          -> if its not, ignore it.
    1217             :         //                           -> if not
    1218             :         //                               ->check to see if any previous setting met the conditioning load
    1219             :         //                                   ->if not:
    1220             :         //                                       ->see if this setting is better at meeting the conditioning load than
    1221             :         // any previous setting this calculation step.
    1222             :         //                                           -> if so save as current optimal
    1223             :         //                                           -> if its not, ignore it.
    1224             :         //                                   -> if so: then ignore it.
    1225             :         //              ->if not, then a previous setting is better than this one by default, and so ignore it.
    1226             :         // 9) Identify error states if the no setting meets the environmental conditions, or the supply air humidity or temperature constraints.
    1227             :         // 10) if we met the load set operating settings to be a combination of the optimal setting at the minium required runtime fraction
    1228             :         // 11) if we partly met the load then do the best we can and run full out in that optimal setting.
    1229             :         // 12) if we didn't even partially meet the load make sure the operational settings are just the standby mode.
    1230             :         // 13) generate summary statistics for warnings.
    1231             : 
    1232             :         // REFERENCES:
    1233             :         // na
    1234             : 
    1235             :         // Using/Aliasing
    1236             : 
    1237             :         // Locals
    1238             :         // SUBROUTINE ARGUMENT DEFINITIONS:
    1239             :         // The CStepInputs are defined in the CStepInputs class definition.
    1240             :         // SUBROUTINE PARAMETER DEFINITIONS:
    1241             :         // na
    1242             :         // INTERFACE BLOCK SPECIFICATIONS
    1243             :         // na
    1244             :         // DERIVED TYPE DEFINITIONS
    1245             :         // na
    1246             : 
    1247             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1248       13217 :         bool DidWeMeetLoad = false;
    1249       13217 :         bool DidWeMeetHumidificaiton = false;
    1250       13217 :         bool DidWePartlyMeetLoad = false;
    1251       13217 :         Real64 OptimalSetting_RunFractionTotalFuel = IMPLAUSIBLE_POWER;
    1252             :         Real64 Tma;
    1253             :         Real64 Wma;
    1254             :         Real64 Hsa;
    1255             :         Real64 Hma;
    1256       13217 :         Real64 PreviousMaxiumConditioningOutput = 0;
    1257       13217 :         Real64 PreviousMaxiumHumidOrDehumidOutput = 0;
    1258       13217 :         std::string ObjectID = Name.c_str();
    1259       13217 :         if (StepIns.RHosa > 1) {
    1260           0 :             ShowSevereError(state,
    1261           0 :                             format("Unitary hybrid system error, required relative humidity value 0-1, called in object{}.Check inputs", ObjectID));
    1262             :             assert(true);
    1263           0 :             return -1;
    1264             :         } // because it should be fractional, this should only really be possible if its called from a unit test
    1265             : 
    1266       13217 :         if (StepIns.RHra > 1) {
    1267           0 :             ShowSevereError(state,
    1268           0 :                             format("Unitary hybrid system error,  required relative humidity value 0-1, called in object{}.Check inputs", ObjectID));
    1269             :             assert(true);
    1270           0 :             return -1;
    1271             :         } // because it should be fractional, this should only really be possible if its called from a unit test
    1272             : 
    1273       13217 :         Real64 Wosa = PsyWFnTdbRhPb(state, StepIns.Tosa, StepIns.RHosa, state.dataEnvrn->OutBaroPress);
    1274       13217 :         Real64 Wra = PsyWFnTdbRhPb(state, StepIns.Tra, StepIns.RHra, InletPressure);
    1275             :         bool EnvironmentConditionsMet, EnvironmentConditionsMetOnce, MinVRMet, SAT_OC_Met, SAT_OC_MetOnce, SARH_OC_Met, SAHR_OC_MetOnce;
    1276       13217 :         EnvironmentConditionsMetOnce = SAT_OC_Met = SAT_OC_MetOnce = SARH_OC_Met = SAHR_OC_MetOnce = false;
    1277             : 
    1278       13217 :         MinOA_Msa = StepIns.MinimumOA; // Set object version of minimum VR Kg/s
    1279             : 
    1280       92519 :         for (std::vector<CMode>::const_iterator iterator = OperatingModes.begin() + 1; iterator != OperatingModes.end();
    1281       66085 :              ++iterator) // iterate though the modes.
    1282             :         {
    1283       66085 :             CMode Mode = *iterator;
    1284       66085 :             bool SAHR_OC_MetinMode = false;
    1285       66085 :             bool SAT_OC_MetinMode = false;
    1286       66085 :             int solution_map_sizeX = Mode.sol.MassFlowRatio.size();
    1287       66085 :             int solution_map_sizeY = Mode.sol.OutdoorAirFraction.size();
    1288             : 
    1289             :             // Check that in this mode the //Outdoor Air Relative Humidity(0 - 100 % )    //Outdoor Air Humidity Ratio(g / g)//Outdoor Air
    1290             :             // Temperature(degC)
    1291       66085 :             if (Mode.MeetsOAEnvConstraints(StepIns.Tosa, Wosa, 100 * StepIns.RHosa)) {
    1292       66085 :                 EnvironmentConditionsMet = EnvironmentConditionsMetOnce = true;
    1293             :             } else {
    1294           0 :                 EnvironmentConditionsMet = false;
    1295             :             }
    1296             : 
    1297       66085 :             if (EnvironmentConditionsMet) {
    1298      436161 :                 for (int indexMassFlowRatio = 0; indexMassFlowRatio < solution_map_sizeX;
    1299             :                      indexMassFlowRatio++) // within each mode go though all the combinations of solution spaces.
    1300             :                 {
    1301      740152 :                     for (int indexOutdoorAirFraction = 0; indexOutdoorAirFraction < solution_map_sizeY; indexOutdoorAirFraction++) {
    1302             :                         // Supply Air Mass Flow Rate(kg / s)
    1303             :                         // Outdoor Air Fraction(0 - 1)
    1304             : 
    1305      370076 :                         Real64 MsaRatio = Mode.sol.MassFlowRatio[indexMassFlowRatio]; // fractions of rated mass flow rate, so for some modes this
    1306             :                                                                                       // might be low but others hi
    1307      370076 :                         Real64 OSAF = Mode.sol.OutdoorAirFraction[indexOutdoorAirFraction];
    1308      370076 :                         Real64 ScaledMsa = ScaledSystemMaximumSupplyAirMassFlowRate * MsaRatio;
    1309      370076 :                         Real64 UnscaledMsa = ScaledSystemMaximumSupplyAirMassFlowRate / ScalingFactor;
    1310      370076 :                         Real64 Supply_Air_Ventilation_Volume = 0;
    1311             :                         // Calculate the ventilation mass flow rate
    1312      370076 :                         Real64 Mvent = ScaledMsa * OSAF;
    1313             : 
    1314      370076 :                         if (state.dataEnvrn->StdRhoAir > 1) {
    1315      370076 :                             Supply_Air_Ventilation_Volume = Mvent / state.dataEnvrn->StdRhoAir;
    1316             :                         } else {
    1317           0 :                             Supply_Air_Ventilation_Volume = Mvent / 1.225; // stored as volumetric flow for reporting
    1318             :                         }
    1319             : 
    1320      370076 :                         if (Mvent - MinOA_Msa > -0.000001) {
    1321      221180 :                             MinVRMet = true;
    1322             :                         } else {
    1323      148896 :                             MinVRMet = false;
    1324             :                         }
    1325             : 
    1326      370076 :                         if (MinVRMet) {
    1327             :                             // reset outside air temp and return air temp before calculating curve values for each mode
    1328      221180 :                             StepIns.Tosa = SecInletTemp;
    1329      221180 :                             StepIns.Tra = InletTemp;
    1330             :                             Real64 FanPower =
    1331      221180 :                                 Mode.CalculateCurveVal(state, StepIns.Tosa, Wosa, StepIns.Tra, Wra, UnscaledMsa, OSAF, SUPPLY_FAN_POWER) *
    1332      221180 :                                 ScalingFactor;
    1333             : 
    1334             :                             // calculate power loss to air if in mixed air stream and divide fan heat between outside air stream and return air stream
    1335      221180 :                             if (FanHeatGain && FanHeatGainLocation == "MIXEDAIRSTREAM") {
    1336           0 :                                 PowerLossToAir = FanPower * FanHeatInAirFrac;
    1337             :                             } else {
    1338      221180 :                                 PowerLossToAir = 0.0;
    1339             :                             }
    1340      221180 :                             Real64 FanHeatTempOA = PowerLossToAir / (PsyCpAirFnW(Wosa) * (ScaledMsa * OSAF));
    1341      221180 :                             StepIns.Tosa = StepIns.Tosa + FanHeatTempOA;
    1342      221180 :                             if (OSAF < 1.0) {
    1343           0 :                                 Real64 FanHeatTempRA = PowerLossToAir / (PsyCpAirFnW(Wra) * (ScaledMsa * (1 - OSAF)));
    1344           0 :                                 StepIns.Tra = StepIns.Tra + FanHeatTempRA;
    1345             :                             }
    1346             : 
    1347             :                             // Calculate prospective supply air temperature
    1348      221180 :                             Tsa = Mode.CalculateCurveVal(state, StepIns.Tosa, Wosa, StepIns.Tra, Wra, UnscaledMsa, OSAF, TEMP_CURVE);
    1349             :                             // Calculate prospective supply air Humidity Ratio
    1350      221180 :                             Wsa = Mode.CalculateCurveVal(state, StepIns.Tosa, Wosa, StepIns.Tra, Wra, UnscaledMsa, OSAF, W_CURVE);
    1351             : 
    1352             :                             // calculate power loss to supply air stream from fan power determined by curve value and fraction of fan heat in air
    1353             :                             // stream
    1354      221180 :                             if (FanHeatGain && FanHeatGainLocation == "SUPPLYAIRSTREAM") {
    1355           0 :                                 PowerLossToAir = FanPower * FanHeatInAirFrac;
    1356             :                             } else {
    1357      221180 :                                 PowerLossToAir = 0.0;
    1358             :                             }
    1359      221180 :                             FanHeatTemp = PowerLossToAir / (PsyCpAirFnW(Wsa) * ScaledMsa);
    1360      221180 :                             Tsa = Tsa + FanHeatTemp;
    1361             : 
    1362             :                             // Check it meets constraints
    1363      221180 :                             if (MeetsSupplyAirTOC(state, Tsa)) {
    1364      100929 :                                 SAT_OC_Met = SAT_OC_MetOnce = SAT_OC_MetinMode = true;
    1365             :                             } else {
    1366      120251 :                                 SAT_OC_Met = false;
    1367             :                             }
    1368             :                             // Return Air Relative Humidity(0 - 100 % ) //Return Air Humidity Ratio(g / g)
    1369      221180 :                             if (MeetsSupplyAirRHOC(state, Wsa)) {
    1370      221180 :                                 SARH_OC_Met = SAHR_OC_MetOnce = SAHR_OC_MetinMode = true;
    1371             :                             } else {
    1372           0 :                                 SARH_OC_Met = false;
    1373             :                             }
    1374             : 
    1375      221180 :                             if (SARH_OC_Met && SAT_OC_Met) {
    1376      100929 :                                 CSetting CandidateSetting;
    1377      100929 :                                 CandidateSetting.Supply_Air_Ventilation_Volume = Supply_Air_Ventilation_Volume;
    1378      100929 :                                 CandidateSetting.Mode = Mode.ModeID;
    1379      100929 :                                 CandidateSetting.Outdoor_Air_Fraction = OSAF;
    1380      100929 :                                 CandidateSetting.Supply_Air_Mass_Flow_Rate_Ratio = MsaRatio;
    1381      100929 :                                 CandidateSetting.Unscaled_Supply_Air_Mass_Flow_Rate = UnscaledMsa;
    1382      100929 :                                 CandidateSetting.ScaledSupply_Air_Mass_Flow_Rate = ScaledMsa;
    1383             : 
    1384             :                                 // If no load is requested but ventilation is required, set the supply air mass flow rate to the minimum of the
    1385             :                                 // required ventilation flow rate and the maximum supply air flow rate
    1386      100929 :                                 if (!CoolingRequested && !HeatingRequested && !DehumidificationRequested && !HumidificationRequested) {
    1387           4 :                                     CandidateSetting.ScaledSupply_Air_Mass_Flow_Rate =
    1388           4 :                                         min(MinOA_Msa, CandidateSetting.ScaledSupply_Air_Mass_Flow_Rate);
    1389             :                                     // add fan heat if not included in lookup tables for supply air stream
    1390           4 :                                     Tsa = StepIns.Tosa + FanHeatTemp;
    1391             :                                 }
    1392             : 
    1393      100929 :                                 CandidateSetting.ScaledSupply_Air_Ventilation_Volume =
    1394      100929 :                                     CandidateSetting.ScaledSupply_Air_Mass_Flow_Rate / state.dataEnvrn->StdRhoAir;
    1395      100929 :                                 CandidateSetting.oMode = Mode;
    1396      100929 :                                 CandidateSetting.SupplyAirTemperature = Tsa;
    1397      100929 :                                 CandidateSetting.SupplyAirW = CheckVal_W(state, Wsa, Tsa, OutletPressure);
    1398      100929 :                                 CandidateSetting.Mode = Mode.ModeID;
    1399      100929 :                                 Settings.push_back(CandidateSetting);
    1400      100929 :                             }
    1401             :                         }
    1402             :                     }
    1403             :                 }
    1404             :             }
    1405       66085 :             if (!state.dataGlobal->WarmupFlag) {
    1406             :                 // Keep an account of the number of times the supply air temperature and humidity constraints were not met for a given mode but only
    1407             :                 // do this when its not warmup.
    1408        9310 :                 if (!SAT_OC_MetinMode) {
    1409        5820 :                     SAT_OC_MetinMode_v[Mode.ModeID] = SAT_OC_MetinMode_v[Mode.ModeID] + 1;
    1410             :                 }
    1411        9310 :                 if (!SAHR_OC_MetinMode) {
    1412        1732 :                     SAHR_OC_MetinMode_v[Mode.ModeID] = SAHR_OC_MetinMode_v[Mode.ModeID] + 1;
    1413             :                 }
    1414             :             }
    1415       79302 :         }
    1416             : 
    1417      114146 :         for (auto &thisSetting : Settings) {
    1418             :             // Calculate the delta H
    1419      100929 :             Real64 OSAF = thisSetting.Outdoor_Air_Fraction;
    1420      100929 :             Real64 UnscaledMsa = thisSetting.Unscaled_Supply_Air_Mass_Flow_Rate;
    1421      100929 :             Real64 ScaledMsa = thisSetting.ScaledSupply_Air_Mass_Flow_Rate;
    1422             : 
    1423             :             // send the scaled Msa to calculate energy and the unscaled for sending to curves.
    1424      100929 :             Tsa = thisSetting.SupplyAirTemperature;
    1425      100929 :             Wsa = thisSetting.SupplyAirW;
    1426      100929 :             Tma = StepIns.Tra + OSAF * (StepIns.Tosa - StepIns.Tra);
    1427      100929 :             Wma = Wra + OSAF * (Wosa - Wra);
    1428      100929 :             thisSetting.Mixed_Air_Temperature = Tma;
    1429      100929 :             thisSetting.Mixed_Air_W = Wma;
    1430             : 
    1431      100929 :             Hma = PsyHFnTdbW(Tma, Wma);
    1432             :             // Calculate Enthalpy of return air
    1433      100929 :             Real64 Hra = PsyHFnTdbW(StepIns.Tra, Wra);
    1434             : 
    1435      100929 :             Hsa = PsyHFnTdbW(Tsa, Wsa);
    1436             : 
    1437      100929 :             Real64 SupplyAirCp = PsyCpAirFnW(Wsa);   // J/degreesK.kg
    1438      100929 :             Real64 ReturnAirCP = PsyCpAirFnW(Wra);   // J/degreesK.kg
    1439      100929 :             Real64 OutdoorAirCP = PsyCpAirFnW(Wosa); // J/degreesK.kg
    1440             : 
    1441             :             // Calculations below of system cooling and heating capacity are ultimately reassessed when the resultant part runtime fraction is
    1442             :             // assessed. However its valuable that they are calculated here to at least provide a check.
    1443             : 
    1444             :             // System Sensible Cooling{ W } = m'SA {kg/s} * 0.5*(cpRA + OSAF*(cpOSA-cpRA) + cpSA) {kJ/kg-C} * (T_RA + OSAF*(T_OSA - T_RA)  - T_SA)
    1445             :             // System Latent Cooling{ W } = m'SAdryair {kg/s} * L {kJ/kgWater} * (HR_RA + OSAF *(HR_OSA - HR_RA) - HR_SA) {kgWater/kgDryAir}
    1446             :             // System Total Cooling{ W } = m'SAdryair {kg/s} * (h_RA + OSAF*(h_OSA - h_RA) - h_SA) {kJ/kgDryAir}
    1447      100929 :             Real64 SystemCp = ReturnAirCP + OSAF * (OutdoorAirCP - ReturnAirCP) + SupplyAirCp; // J/degreesK.kg
    1448      100929 :             Real64 SensibleSystem = ScaledMsa * 0.5 * SystemCp * (Tma - Tsa);                  // W dynamic cp
    1449      100929 :             Real64 MsaDry = ScaledMsa * (1 - Wsa);
    1450      100929 :             Real64 LambdaSa = Psychrometrics::PsyHfgAirFnWTdb(0, Tsa);
    1451      100929 :             Real64 LatentSystem = LambdaSa * MsaDry * (Wma - Wsa); // W
    1452             :                                                                    // Total system cooling
    1453      100929 :             thisSetting.TotalSystem = (Hma - Hsa) * ScaledMsa;
    1454             :             // Perform latent check
    1455             :             // Real64 latentCheck = TotalSystem - SensibleSystem;
    1456             : 
    1457             :             // Zone Sensible Cooling{ W } = m'SA {kg/s} * 0.5*(cpRA+cpSA) {kJ/kg-C} * (T_RA - T_SA) {C}
    1458             :             // Zone Latent Cooling{ W } = m'SAdryair {kg/s} * L {kJ/kgWater} * (HR_RA - HR_SA) {kgWater/kgDryAir}
    1459             :             // Zone Total Cooling{ W } = m'SAdryair {kg/s} * (h_RA - h_SA) {kJ/kgDryAir}
    1460      100929 :             Real64 SensibleRoomORZone = ScaledMsa * 0.5 * (SupplyAirCp + ReturnAirCP) * (StepIns.Tra - Tsa); // W dynamic cp
    1461      100929 :             Real64 latentRoomORZone = LambdaSa * MsaDry * (Wra - Wsa);                                       // W
    1462             :                                                                                                              // Total room cooling
    1463      100929 :             Real64 TotalRoomORZone = (Hra - Hsa) * ScaledMsa;                                                // W
    1464             :                                                                                                              // Perform latent check
    1465             :             // Real64 latentRoomORZoneCheck = TotalRoomORZone - SensibleRoomORZone;
    1466             : 
    1467      100929 :             thisSetting.SensibleSystem = SensibleSystem;
    1468      100929 :             thisSetting.LatentSystem = LatentSystem;
    1469      100929 :             thisSetting.TotalZone = TotalRoomORZone;
    1470      100929 :             thisSetting.SensibleZone = SensibleRoomORZone;
    1471      100929 :             thisSetting.LatentZone = latentRoomORZone;
    1472             : 
    1473      100929 :             bool Conditioning_load_met = false;
    1474      100929 :             if (CoolingRequested && (SensibleRoomORZone > StepIns.RequestedCoolingLoad)) {
    1475       14048 :                 Conditioning_load_met = true;
    1476             :             }
    1477      100929 :             if (HeatingRequested && (SensibleRoomORZone < StepIns.RequestedHeatingLoad)) {
    1478           0 :                 Conditioning_load_met = true;
    1479             :             }
    1480      100929 :             if (!(HeatingRequested || CoolingRequested)) {
    1481       42507 :                 Conditioning_load_met = true;
    1482             :             }
    1483             : 
    1484      100929 :             bool Humidification_load_met = false;
    1485             : 
    1486      100929 :             Real64 RequestedDeHumdificationLoad = StepIns.ZoneDehumidificationLoad;
    1487      100929 :             if (DehumidificationRequested && latentRoomORZone > RequestedDeHumdificationLoad) {
    1488           4 :                 Humidification_load_met = true;
    1489             :             }
    1490      100929 :             Real64 RequestedHumdificationLoad = StepIns.ZoneMoistureLoad;
    1491      100929 :             if (HumidificationRequested && latentRoomORZone < RequestedHumdificationLoad) {
    1492       97595 :                 Humidification_load_met = true;
    1493             :             }
    1494             : 
    1495      100929 :             if (!(HumidificationRequested || DehumidificationRequested)) {
    1496        3326 :                 Humidification_load_met = true;
    1497             :             }
    1498             : 
    1499      100929 :             thisSetting.ElectricalPower = thisSetting.oMode.CalculateCurveVal(
    1500             :                 state, StepIns.Tosa, Wosa, StepIns.Tra, Wra, UnscaledMsa, OSAF, POWER_CURVE); // [Kw] calculations for fuel in Kw
    1501      100929 :             thisSetting.SupplyFanElectricPower =
    1502      100929 :                 thisSetting.oMode.CalculateCurveVal(state, StepIns.Tosa, Wosa, StepIns.Tra, Wra, UnscaledMsa, OSAF, SUPPLY_FAN_POWER);
    1503      100929 :             thisSetting.ExternalStaticPressure =
    1504      100929 :                 thisSetting.oMode.CalculateCurveVal(state, StepIns.Tosa, Wosa, StepIns.Tra, Wra, UnscaledMsa, OSAF, EXTERNAL_STATIC_PRESSURE);
    1505      100929 :             thisSetting.SecondaryFuelConsumptionRate =
    1506      100929 :                 thisSetting.oMode.CalculateCurveVal(state, StepIns.Tosa, Wosa, StepIns.Tra, Wra, UnscaledMsa, OSAF, SECOND_FUEL_USE);
    1507      100929 :             thisSetting.ThirdFuelConsumptionRate =
    1508      100929 :                 thisSetting.oMode.CalculateCurveVal(state, StepIns.Tosa, Wosa, StepIns.Tra, Wra, UnscaledMsa, OSAF, THIRD_FUEL_USE);
    1509      100929 :             thisSetting.WaterConsumptionRate =
    1510      100929 :                 thisSetting.oMode.CalculateCurveVal(state, StepIns.Tosa, Wosa, StepIns.Tra, Wra, UnscaledMsa, OSAF, WATER_USE);
    1511             : 
    1512             :             // Calculate partload fraction required to meet all requirements
    1513      100929 :             Real64 PartRuntimeFraction = 0;
    1514      302787 :             PartRuntimeFraction = CalculatePartRuntimeFraction(MinOA_Msa,
    1515      100929 :                                                                thisSetting.Supply_Air_Ventilation_Volume * state.dataEnvrn->StdRhoAir,
    1516             :                                                                StepIns.RequestedCoolingLoad,
    1517             :                                                                StepIns.RequestedHeatingLoad,
    1518             :                                                                SensibleRoomORZone,
    1519             :                                                                StepIns.ZoneDehumidificationLoad,
    1520             :                                                                StepIns.ZoneMoistureLoad,
    1521             :                                                                latentRoomORZone); //
    1522             : 
    1523      100929 :             Real64 RunFractionTotalFuel =
    1524      100929 :                 thisSetting.ElectricalPower * PartRuntimeFraction; // fraction can be above 1 meaning its not able to do it completely in a time step.
    1525      100929 :             thisSetting.Runtime_Fraction = PartRuntimeFraction;
    1526             : 
    1527      100929 :             if (Conditioning_load_met && Humidification_load_met) {
    1528             :                 // store best performing mode
    1529       56555 :                 if (RunFractionTotalFuel < OptimalSetting_RunFractionTotalFuel) {
    1530        6288 :                     OptimalSetting_RunFractionTotalFuel = RunFractionTotalFuel;
    1531        6288 :                     OptimalSetting = thisSetting;
    1532        6288 :                     DidWeMeetLoad = true;
    1533        6288 :                     DidWeMeetHumidificaiton = true;
    1534             :                 }
    1535             :             } else {
    1536       44374 :                 if (!DidWeMeetLoad && !DidWeMeetHumidificaiton) {
    1537       30298 :                     bool store_best_attempt = false;
    1538             : 
    1539       30298 :                     if (Conditioning_load_met) {
    1540           0 :                         DidWeMeetLoad = true;
    1541           0 :                         if (HumidificationRequested && (latentRoomORZone < PreviousMaxiumHumidOrDehumidOutput)) {
    1542           0 :                             store_best_attempt = true;
    1543             :                         }
    1544           0 :                         if (DehumidificationRequested && (latentRoomORZone > PreviousMaxiumHumidOrDehumidOutput)) {
    1545           0 :                             store_best_attempt = true;
    1546             :                         }
    1547           0 :                         if (store_best_attempt) {
    1548           0 :                             PreviousMaxiumHumidOrDehumidOutput = latentRoomORZone;
    1549             :                         }
    1550             :                     } else {
    1551       30298 :                         if (!DidWeMeetLoad) {
    1552       30298 :                             if (CoolingRequested && (SensibleRoomORZone > PreviousMaxiumConditioningOutput)) {
    1553        1142 :                                 store_best_attempt = true;
    1554             :                             }
    1555       30298 :                             if (HeatingRequested && (SensibleRoomORZone < PreviousMaxiumConditioningOutput)) {
    1556           0 :                                 store_best_attempt = true;
    1557             :                             }
    1558       30298 :                             if (store_best_attempt) {
    1559        1142 :                                 PreviousMaxiumConditioningOutput = SensibleRoomORZone;
    1560             :                             }
    1561             :                         }
    1562             :                     }
    1563       30298 :                     if (store_best_attempt) {
    1564        1142 :                         OptimalSetting_RunFractionTotalFuel = RunFractionTotalFuel;
    1565        1142 :                         OptimalSetting = thisSetting;
    1566        1142 :                         DidWePartlyMeetLoad = true;
    1567             :                     }
    1568             :                 }
    1569             :             }
    1570       13217 :         }
    1571             : 
    1572       13217 :         if (!EnvironmentConditionsMetOnce) {
    1573           0 :             ErrorCode = 1;
    1574           0 :             count_EnvironmentConditionsNotMet++;
    1575             :         }
    1576       13217 :         if (!SAHR_OC_MetOnce) {
    1577           0 :             count_SAHR_OC_MetOnce++;
    1578           0 :             ErrorCode = 2;
    1579             :         }
    1580       13217 :         if (!SAT_OC_MetOnce) {
    1581           0 :             count_SAT_OC_MetOnce++;
    1582           0 :             ErrorCode = 3;
    1583             :         }
    1584             :         // if we met the load set operating settings to be a combination of the optimal setting at the minium required runtime fraction
    1585       13217 :         if (DidWeMeetLoad) {
    1586             :             // add first setting to operating modes
    1587        4393 :             ErrorCode = 0;
    1588             :             // save the optimal setting in the
    1589        4393 :             CurrentOperatingSettings[0] = OptimalSetting;
    1590        4393 :             PrimaryModeRuntimeFraction = OptimalSetting.Runtime_Fraction;
    1591        4393 :             oStandBy.Runtime_Fraction = (1 - PrimaryModeRuntimeFraction);
    1592        4393 :             if (oStandBy.Runtime_Fraction < 0) {
    1593           0 :                 oStandBy.Runtime_Fraction = 0;
    1594             :             }
    1595        4393 :             CurrentOperatingSettings[1] = oStandBy;
    1596             :         } else {
    1597             :             // if we partly met the load then do the best we can and run full out in that optimal setting.
    1598        8824 :             if (!DidWeMeetLoad && DidWePartlyMeetLoad) {
    1599        1142 :                 ErrorCode = 0;
    1600        1142 :                 count_DidWeNotMeetLoad++;
    1601        1142 :                 if (OptimalSetting.ElectricalPower == IMPLAUSIBLE_POWER) {
    1602           0 :                     ShowWarningError(state, "Model was not able to provide cooling for a time step, called in HybridEvapCooling:dostep");
    1603           0 :                     OptimalSetting.ElectricalPower = 0;
    1604             :                 }
    1605        1142 :                 OptimalSetting.Runtime_Fraction = 1;
    1606        1142 :                 CurrentOperatingSettings[0] = OptimalSetting;
    1607        1142 :                 PrimaryMode = OptimalSetting.Mode;
    1608        1142 :                 PrimaryModeRuntimeFraction = 1;
    1609             :             }
    1610             :             // if we didn't even partially meet the load make sure the operational settings are just the standby mode.
    1611             :             else {
    1612        7682 :                 oStandBy.Runtime_Fraction = 1;
    1613        7682 :                 CurrentOperatingSettings[0] = oStandBy;
    1614        7682 :                 ErrorCode = -1;
    1615        7682 :                 StandBy = true;
    1616        7682 :                 count_DidWeNotMeetLoad++;
    1617             :             }
    1618             :         }
    1619             : 
    1620             :         Real64 TimeElapsed =
    1621       13217 :             state.dataGlobal->HourOfDay + state.dataGlobal->TimeStep * state.dataGlobal->TimeStepZone + state.dataHVACGlobal->SysTimeElapsed;
    1622             : 
    1623             :         // Use the elapsed time to only give a summary of warnings related to the number of Timesteps environmental conditions, or supply air
    1624             :         // temperature constraints were not met for a given day. ideally there would be a clear flag that indicates "this is the last timestep of the
    1625             :         // day, so report", but that doesn't seem to exist.
    1626       13217 :         if ((TimeElapsed > 24) && WarnOnceFlag && !state.dataGlobal->WarmupFlag) {
    1627           2 :             if (count_EnvironmentConditionsNotMet > 0)
    1628           0 :                 ShowWarningError(state,
    1629           0 :                                  format("In day {:.1R} was unable to operate for  of simulation, {}{:.1R} timesteps because environment conditions "
    1630             :                                         "were beyond the allowable operating range for any mode.",
    1631           0 :                                         (Real64)state.dataGlobal->DayOfSim,
    1632           0 :                                         Name,
    1633           0 :                                         (Real64)count_EnvironmentConditionsNotMet));
    1634           2 :             if (count_SAHR_OC_MetOnce > 0)
    1635           0 :                 ShowWarningError(state,
    1636           0 :                                  format("In day {:.1R} of simulation, {} failed to meet supply air humidity ratio for {:.1R} time steps. For these "
    1637             :                                         "time steps For these time steps was set to mode 0{}",
    1638           0 :                                         (Real64)state.dataGlobal->DayOfSim,
    1639           0 :                                         Name,
    1640           0 :                                         Real64(count_SAHR_OC_MetOnce),
    1641           0 :                                         Name));
    1642           2 :             if (count_SAT_OC_MetOnce > 0)
    1643           0 :                 ShowWarningError(state,
    1644           0 :                                  format("In day {:.1R} of simulation, {} failed to meet supply air temperature constraints for {:.1R} time steps. "
    1645             :                                         "For these time steps For these time steps{} was set to mode 0",
    1646           0 :                                         (Real64)state.dataGlobal->DayOfSim,
    1647           0 :                                         Name,
    1648           0 :                                         Real64(count_SAT_OC_MetOnce),
    1649           0 :                                         Name));
    1650             : 
    1651           4 :             ShowWarningError(state,
    1652           4 :                              format("In day {:.1R} of simulation, {} failed to  satisfy sensible load for {:.1R} time steps. For these time steps "
    1653             :                                     "settings were selected to provide as much sensible cooling or heating as possible, given other constraints.",
    1654           2 :                                     (Real64)state.dataGlobal->DayOfSim,
    1655           2 :                                     Name,
    1656           2 :                                     (Real64)count_DidWeNotMeetLoad));
    1657             : 
    1658           2 :             count_SAT_OC_MetOnce = 0;
    1659           2 :             count_DidWeNotMeetLoad = 0;
    1660           2 :             count_SAHR_OC_MetOnce = 0;
    1661           2 :             count_EnvironmentConditionsMetOnce = 0;
    1662           2 :             count_EnvironmentConditionsNotMet = 0;
    1663           2 :             WarnOnceFlag = false;
    1664             :         }
    1665       13217 :         if (state.dataGlobal->HourOfDay == 1 && !WarnOnceFlag && !state.dataGlobal->WarmupFlag) {
    1666           2 :             WarnOnceFlag = true;
    1667             :         }
    1668       13217 :         return ErrorCode;
    1669       13217 :     }
    1670             : 
    1671        5535 :     int Model::CurrentPrimaryMode()
    1672             :     {
    1673             :         // SUBROUTINE INFORMATION:
    1674             :         //       AUTHOR         Spencer Maxwell Dutton
    1675             :         //       DATE WRITTEN   October 2017
    1676             :         //       MODIFIED
    1677             :         //       RE-ENGINEERED  na
    1678             : 
    1679             :         // PURPOSE OF THIS SUBROUTINE:
    1680             :         // retunrs the primary mode of operation
    1681             : 
    1682             :         // METHODOLOGY EMPLOYED:
    1683             :         //
    1684             : 
    1685             :         // REFERENCES:
    1686             :         // na
    1687             : 
    1688             :         // Using/Aliasing
    1689             : 
    1690        5535 :         if (CurrentOperatingSettings.size() > 0) {
    1691        5535 :             return CurrentOperatingSettings[0].Mode;
    1692             :         } else
    1693           0 :             return -1;
    1694             :     }
    1695        5535 :     Real64 Model::CurrentPrimaryRuntimeFraction()
    1696             :     {
    1697             :         // SUBROUTINE INFORMATION:
    1698             :         //       AUTHOR         Spencer Maxwell Dutton
    1699             :         //       DATE WRITTEN   October 2017
    1700             :         //       MODIFIED
    1701             :         //       RE-ENGINEERED  na
    1702             : 
    1703             :         // PURPOSE OF THIS SUBROUTINE:
    1704             :         // returns the runtime fraction of the primary setting.
    1705             : 
    1706             :         // METHODOLOGY EMPLOYED:
    1707             :         //
    1708             : 
    1709             :         // REFERENCES:
    1710             :         // na
    1711             : 
    1712             :         // Using/Aliasing
    1713        5535 :         if (CurrentOperatingSettings.size() > 0) {
    1714        5535 :             return CurrentOperatingSettings[0].Runtime_Fraction;
    1715             :         } else
    1716           0 :             return -1;
    1717             :     }
    1718       13275 :     void Model::DetermineCoolingVentilationOrHumidificationNeeds(CStepInputs &StepIns)
    1719             :     {
    1720             :         // SUBROUTINE INFORMATION:
    1721             :         //       AUTHOR         Spencer Maxwell Dutton
    1722             :         //       DATE WRITTEN   October 2017
    1723             :         //       MODIFIED
    1724             :         //       RE-ENGINEERED  na
    1725             : 
    1726             :         // PURPOSE OF THIS SUBROUTINE:
    1727             :         // Sets member boolean variables to establish if the Cooling, Heating, ventilation or dehumidifcation needs are met.
    1728             : 
    1729             :         // METHODOLOGY EMPLOYED:
    1730             :         //
    1731             : 
    1732             :         // REFERENCES:
    1733             :         // na
    1734             : 
    1735             :         // Using/Aliasing
    1736       13275 :         CoolingRequested = false;
    1737       13275 :         HeatingRequested = false;
    1738       13275 :         VentilationRequested = false;
    1739       13275 :         DehumidificationRequested = false;
    1740       13275 :         HumidificationRequested = false;
    1741             :         // establish if conditioning needed
    1742       13275 :         if (StepIns.RequestedCoolingLoad >= MINIMUM_LOAD_TO_ACTIVATE) {
    1743        2656 :             CoolingRequested = true;
    1744        2656 :             StepIns.RequestedHeatingLoad = 0;
    1745             :         }
    1746       13275 :         if (StepIns.RequestedHeatingLoad <= -MINIMUM_LOAD_TO_ACTIVATE) {
    1747        7682 :             HeatingRequested = true;
    1748        7682 :             StepIns.RequestedCoolingLoad = 0;
    1749             :         }
    1750             :         // establish if ventilation needed
    1751       13275 :         if (StepIns.MinimumOA > 0) VentilationRequested = true;
    1752             :         // Load required to meet dehumidifying setpoint (<0 = a dehumidify load)  [kgWater/s]
    1753       13275 :         if (StepIns.ZoneDehumidificationLoad < 0) {
    1754           4 :             DehumidificationRequested = true;
    1755           4 :             StepIns.ZoneMoistureLoad = 0;
    1756             :         }
    1757             :         // Load required to meet humidifying setpoint (>0 = a humidify load) [kgWater/s]
    1758       13275 :         if (StepIns.ZoneMoistureLoad > 0) {
    1759       12333 :             StepIns.ZoneDehumidificationLoad = 0;
    1760       12333 :             HumidificationRequested = true;
    1761             :         }
    1762       13275 :     }
    1763             : 
    1764             :     // doStep is passed some variables that could have just used the class members, but this adds clarity about whats needed, especially helpful in
    1765             :     // unit testing
    1766       13275 :     void Model::doStep(EnergyPlusData &state,
    1767             :                        Real64 RequestedCoolingLoad,       // in joules, cooling load as negitive
    1768             :                        Real64 RequestedHeatingLoad,       // in joules, heating load as positive
    1769             :                        Real64 OutputRequiredToHumidify,   // Load required to meet humidifying setpoint (>0 = a humidify load) [kgWater/s]
    1770             :                        Real64 OutputRequiredToDehumidify, // Load required to meet dehumidifying setpoint (<0 = a dehumidify load)  [kgWater/s]
    1771             :                        Real64 DesignMinVR)                // mass flow rate of design ventilation air kg/s
    1772             :     {
    1773             :         // SUBROUTINE INFORMATION:
    1774             :         //       AUTHOR         Spencer Dutton
    1775             :         //       DATE WRITTEN   May 2017
    1776             :         //       MODIFIED       na
    1777             :         //       RE-ENGINEERED  na
    1778             : 
    1779             :         // PURPOSE OF THIS SUBROUTINE:
    1780             :         // This subroutine Model::doStep, the main calculation steps
    1781             :         // 1)Collate required inputs into a CStepInputs, this helps with the unit tests
    1782             :         //   so we always know what values need to be set.
    1783             :         // 2)Calculate W humidity ratios for outdoor air and return air.
    1784             :         // 3)Sets boolean values for each potential conditioning requirement;
    1785             :         //   CoolingRequested, HeatingRequested, VentilationRequested, DehumidificationRequested, HumidificationRequested
    1786             :         // 4)Take the first operating mode which is always standby and calculate the use curves to determine performance metrics for
    1787             :         //   the standby mode including energy use and other outputs
    1788             :         // 5)Test system availbility status and go into standby if unit is off or not needed (booleans listed in 3 are all false)
    1789             :         // 6) Set the operating conditions and respective part load fractions.
    1790             :         // 7) Set timestep average outlet condition, considering all operating conditions and runtimes.
    1791             :         // METHODOLOGY EMPLOYED:
    1792             :         // na
    1793             : 
    1794             :         // REFERENCES: OutletVolumetricFlowRate, SupplyVentilationVolume, MinOA_Msa, SupplyVentilationAir
    1795             :         // na
    1796             : 
    1797             :         // set requested loads to output variables
    1798       13275 :         RequestedLoadToHeatingSetpoint = RequestedHeatingLoad;
    1799       13275 :         RequestedLoadToCoolingSetpoint = RequestedCoolingLoad;
    1800       13275 :         Real64 LambdaRa = Psychrometrics::PsyHfgAirFnWTdb(0, InletTemp);
    1801       13275 :         RequestedHumdificationMass = OutputRequiredToHumidify;
    1802       13275 :         RequestedHumdificationLoad = OutputRequiredToHumidify * LambdaRa;                                          // [W];
    1803       13275 :         RequestedHumdificationEnergy = OutputRequiredToHumidify * LambdaRa * state.dataHVACGlobal->TimeStepSysSec; // [j]
    1804             : 
    1805       13275 :         RequestedDeHumdificationMass = OutputRequiredToDehumidify;
    1806       13275 :         RequestedDeHumdificationLoad = OutputRequiredToDehumidify * LambdaRa;                                          // [W];
    1807       13275 :         RequestedDeHumdificationEnergy = OutputRequiredToDehumidify * LambdaRa * state.dataHVACGlobal->TimeStepSysSec; // [j]
    1808             : 
    1809       13275 :         MinOA_Msa = DesignMinVR; // as mass flow kg/s
    1810             : 
    1811             :         // Collate all the inputs required for calculation into one local data structure CStepInputs, this helps with the unit tests so we always know
    1812             :         // what values need to be set
    1813       13275 :         CStepInputs StepIns;
    1814       13275 :         StepIns.Tosa = SecInletTemp; // degrees C
    1815       13275 :         StepIns.Tra = InletTemp;     // degrees C
    1816       13275 :         StepIns.RHosa = SecInletRH;  // RH as 0-1
    1817       13275 :         StepIns.RHra = InletRH;
    1818             :         // For historical reasons cooling is  positive, heating negative throughout the calculation
    1819       13275 :         StepIns.RequestedCoolingLoad = -RequestedCoolingLoad; // Cooling positive now, heating negative
    1820       13275 :         StepIns.RequestedHeatingLoad = -RequestedHeatingLoad; // Cooling positive now, heating negative
    1821             : 
    1822       13275 :         StepIns.ZoneMoistureLoad = RequestedHumdificationLoad;
    1823       13275 :         StepIns.ZoneDehumidificationLoad = RequestedDeHumdificationLoad;
    1824       13275 :         StepIns.MinimumOA = DesignMinVR;
    1825             :         // calculate W humidity ratios for outdoor air and return air
    1826       13275 :         Real64 Wosa = PsyWFnTdbRhPb(state, StepIns.Tosa, StepIns.RHosa, state.dataEnvrn->OutBaroPress);
    1827       13275 :         Real64 Wra = PsyWFnTdbRhPb(state, StepIns.Tra, StepIns.RHra, InletPressure);
    1828             :         // Sets boolean values for each potential conditioning requirement;  CoolingRequested, HeatingRequested, VentilationRequested,
    1829             :         // DehumidificationRequested, HumidificationRequested
    1830       13275 :         DetermineCoolingVentilationOrHumidificationNeeds(StepIns);
    1831             :         // Take the first operating mode which is always standby and calculate the curve values
    1832             :         // to determine performance metrics for the standby mode including energy use and other outputs
    1833             : 
    1834       13275 :         CMode Mode = *(OperatingModes.begin());
    1835       13275 :         if (SetStandByMode(state, Mode, StepIns.Tosa, Wosa, StepIns.Tra, Wra)) {
    1836           0 :             std::string ObjectID = Name.c_str();
    1837           0 :             ShowSevereError(state,
    1838           0 :                             format("Standby mode not defined correctly, as the mode is defined there are zero combinations of acceptible outside air "
    1839             :                                    "fractions and supply air mass flow rate, called in object {}",
    1840             :                                    ObjectID));
    1841           0 :         }
    1842             :         // Test system availability status
    1843       13275 :         UnitOn = 1;
    1844       13275 :         bool ForceOff = false;
    1845       13275 :         StandBy = false;
    1846       13275 :         if (GetCurrentScheduleValue(state, SchedPtr) <= 0 || availStatus == Avail::Status::ForceOff) {
    1847           0 :             UnitOn = 0;
    1848           0 :             ForceOff = true;
    1849             :         }
    1850             : 
    1851             :         // Initialize all settings for all operating modes
    1852       13275 :         int size = CurrentOperatingSettings.size();
    1853       13275 :         CSetting empty_setting;
    1854       66375 :         for (int i = 1; i < size; i++) {
    1855       53100 :             CurrentOperatingSettings[i] = empty_setting;
    1856             :         }
    1857             : 
    1858             :         // Go into standby if unit is off or not needed
    1859       13275 :         if ((!CoolingRequested && !HeatingRequested && !VentilationRequested && !HumidificationRequested && !DehumidificationRequested) || ForceOff) {
    1860          58 :             StandBy = true;
    1861          58 :             oStandBy.Runtime_Fraction = 1;
    1862          58 :             CurrentOperatingSettings[0] = oStandBy;
    1863          58 :             ErrorCode = 0;
    1864          58 :             PrimaryMode = 0;
    1865          58 :             PrimaryModeRuntimeFraction = 0;
    1866             :         } else {
    1867             :             // set the operating conditions and respective part load fractions.
    1868       13217 :             ErrorCode = SetOperatingSetting(state, StepIns);
    1869             :         }
    1870             : 
    1871       13275 :         Real64 QTotZoneOut = 0;
    1872             :         // now class members QSensZoneOut = 0;
    1873             :         // QLatentZoneOut = 0;
    1874             : 
    1875       13275 :         Real64 QTotSystemOut = 0;
    1876       13275 :         Real64 QSensSystemOut = 0;
    1877       13275 :         Real64 QLatentSystemOut = 0;
    1878             :         // Even if its off or in standby we still need to continue to calculate standby loads
    1879             :         // All powers are calculated in Watts amd energies in Joules
    1880             : 
    1881       13275 :         SupplyVentilationVolume = CalculateTimeStepAverage(SYSTEMOUTPUTS::VENTILATION_AIR_V);
    1882       13275 :         if (state.dataEnvrn->StdRhoAir > 1) {
    1883       13275 :             SupplyVentilationAir = SupplyVentilationVolume * state.dataEnvrn->StdRhoAir;
    1884             :         } else {
    1885           0 :             SupplyVentilationAir = SupplyVentilationVolume * 1.225;
    1886             :         }
    1887             :         // set timestep average outlet condition, considering all operating conditions and runtimes.
    1888       13275 :         OutletTemp = CheckVal_T(state, CalculateTimeStepAverage(SYSTEMOUTPUTS::SUPPLY_AIR_TEMP));
    1889       13275 :         OutletHumRat = CheckVal_W(state, CalculateTimeStepAverage(SYSTEMOUTPUTS::SUPPLY_AIR_HR), OutletTemp, OutletPressure);
    1890             : 
    1891       13275 :         OutletRH = PsyRhFnTdbWPb(state, OutletTemp, OutletHumRat, OutletPressure);
    1892       13275 :         Real64 OperatingAverageMixedAirTemperature = CalculateTimeStepAverage(SYSTEMOUTPUTS::MIXED_AIR_TEMP);
    1893       13275 :         Real64 OperatingMixedAirW = CalculateTimeStepAverage(SYSTEMOUTPUTS::MIXED_AIR_HR);
    1894       13275 :         Real64 MixedAirEnthalpy = PsyHFnTdbW(OperatingAverageMixedAirTemperature, OperatingMixedAirW);
    1895       13275 :         OutletEnthalpy = PsyHFnTdbRhPb(state, OutletTemp, OutletRH, InletPressure);
    1896       13275 :         OutletMassFlowRate = CalculateTimeStepAverage(SYSTEMOUTPUTS::SUPPLY_MASS_FLOW);
    1897             : 
    1898       13275 :         if (state.dataEnvrn->StdRhoAir > 1) {
    1899       13275 :             OutletVolumetricFlowRate = OutletMassFlowRate / state.dataEnvrn->StdRhoAir;
    1900             :         } else {
    1901           0 :             OutletVolumetricFlowRate = OutletMassFlowRate / 1.225;
    1902             :         }
    1903             : 
    1904       13275 :         if (!StandBy) {
    1905        5535 :             if (OutletMassFlowRate > 0) {
    1906        5535 :                 averageOSAF = SupplyVentilationAir / OutletMassFlowRate;
    1907             :             } else {
    1908           0 :                 std::string ObjectID = Name.c_str();
    1909           0 :                 if (CoolingRequested || HeatingRequested) {
    1910           0 :                     ShowSevereError(
    1911             :                         state,
    1912           0 :                         format("Outlet air mass flow rate of zero during period with conditioning need, check mode definition. Called in object {}",
    1913           0 :                                Name));
    1914             :                 }
    1915           0 :                 averageOSAF = 1;
    1916           0 :             }
    1917             :             // Calculate timestep average unit and system
    1918        5535 :             PrimaryMode = CurrentPrimaryMode();
    1919        5535 :             PrimaryModeRuntimeFraction = CurrentPrimaryRuntimeFraction();
    1920        5535 :             Real64 Outletcp = PsyCpAirFnW(OutletHumRat); // J/degreesK.kg
    1921        5535 :             Real64 Returncp = PsyCpAirFnW(Wra);          // J/degreesK.kg
    1922        5535 :             Real64 Outdoorcp = PsyCpAirFnW(Wosa);        // J/degreesK.kg
    1923             :             // Zone Sensible Cooling{ W } = m'SA {kg/s} * 0.5*(cpRA+cpSA) {kJ/kg-C} * (T_RA - T_SA) {C}
    1924             :             // Zone Latent Cooling{ W } = m'SAdryair {kg/s} * L {kJ/kgWater} * (HR_RA - HR_SA) {kgWater/kgDryAir}
    1925             :             // Zone Total Cooling{ W } = m'SAdryair {kg/s} * (h_RA - h_SA) {kJ/kgDryAir}
    1926        5535 :             QSensZoneOut = OutletMassFlowRate * 0.5 * (Returncp + Outletcp) * (StepIns.Tra - OutletTemp); // Watts
    1927        5535 :             Real64 OutletMassFlowRateDry = OutletMassFlowRate * (1 - Wsa);
    1928        5535 :             Real64 LambdaSa = Psychrometrics::PsyHfgAirFnWTdb(0, OutletTemp);
    1929        5535 :             QLatentZoneOutMass = OutletMassFlowRateDry * (InletHumRat - OutletHumRat); // Watts
    1930        5535 :             QLatentZoneOut = QLatentZoneOutMass * LambdaSa;
    1931        5535 :             QTotZoneOut = OutletMassFlowRateDry * (InletEnthalpy - OutletEnthalpy); // Watts
    1932        5535 :             Real64 QLatentCheck = QTotZoneOut - QSensZoneOut;                       // Watts
    1933             : 
    1934             :             // System Sensible Cooling{ W } = m'SA {kg/s} * 0.5*(cpRA + OSAF*(cpOSA-cpRA) + cpSA) {kJ/kg-C} * (T_RA + OSAF*(T_OSA - T_RA)  - T_SA)
    1935             :             // System Latent Cooling{ W } = m'SAdryair {kg/s} * L {kJ/kgWater} * (HR_RA + OSAF *(HR_OSA - HR_RA) - HR_SA) {kgWater/kgDryAir}
    1936             :             // System Total Cooling{ W } = m'SAdryair {kg/s} * (h_RA + OSAF*(h_OSA - h_RA) - h_SA) {kJ/kgDryAir}
    1937             : 
    1938        5535 :             Real64 SystemTimeStepCp = Returncp + averageOSAF * (Outdoorcp - Returncp) + Outletcp; // cpRA + OSAF*(cpOSA-cpRA) + cpSA //J/degreesK.kg
    1939        5535 :             Real64 SystemTimeStepW = InletHumRat + averageOSAF * (Wosa - Wra) - OutletHumRat;     // HR_RA + OSAF *(HR_OSA - HR_RA) - HR_SA
    1940        5535 :             Real64 SystemTimeStepT = StepIns.Tra + averageOSAF * (StepIns.Tosa - StepIns.Tra) - OutletTemp; // T_RA + OSAF *(T_OSA - T_RA) - T_SA
    1941        5535 :             QSensSystemOut = 0.5 * SystemTimeStepCp * OutletMassFlowRate * SystemTimeStepT;                 // Watts
    1942             : 
    1943        5535 :             QLatentSystemOut = LambdaSa * OutletMassFlowRateDry * SystemTimeStepW;       // Watts
    1944        5535 :             QTotSystemOut = OutletMassFlowRateDry * (MixedAirEnthalpy - OutletEnthalpy); // Watts
    1945        5535 :             QLatentCheck = QTotSystemOut - QSensSystemOut;                               // Watts
    1946             : 
    1947             :             // reset outputs
    1948        5535 :             ResetOutputs();
    1949             :             // set UNIT outputs for cooling and heating
    1950        5535 :             if (QTotZoneOut > 0) // zone cooling is positive, else remain zero
    1951             :             {
    1952        4044 :                 UnitTotalCoolingRate = std::abs(QTotZoneOut);                                         // Watts
    1953        4044 :                 UnitTotalCoolingEnergy = UnitTotalCoolingRate * state.dataHVACGlobal->TimeStepSysSec; // J
    1954             :             } else {
    1955        1491 :                 UnitTotalHeatingRate = std::abs(QTotZoneOut);                                         // Watts
    1956        1491 :                 UnitTotalHeatingEnergy = UnitTotalHeatingRate * state.dataHVACGlobal->TimeStepSysSec; // J
    1957             :             }
    1958             : 
    1959        5535 :             if (QSensZoneOut > 0) // zone cooling is positive, else remain zero
    1960             :             {
    1961        4039 :                 UnitSensibleCoolingRate = std::abs(QSensZoneOut);                                           // Watts
    1962        4039 :                 UnitSensibleCoolingEnergy = UnitSensibleCoolingRate * state.dataHVACGlobal->TimeStepSysSec; // J
    1963             :             } else {
    1964        1496 :                 UnitSensibleHeatingRate = std::abs(QSensZoneOut);                                           // Watts
    1965        1496 :                 UnitSensibleHeatingEnergy = UnitSensibleHeatingRate * state.dataHVACGlobal->TimeStepSysSec; // J
    1966             :             }
    1967             : 
    1968        5535 :             if ((UnitTotalCoolingRate - UnitSensibleCoolingRate) > 0) {
    1969        1654 :                 UnitLatentCoolingRate = UnitTotalCoolingRate - UnitSensibleCoolingRate;       // Watts
    1970        1654 :                 UnitLatentCoolingEnergy = UnitTotalCoolingEnergy - UnitSensibleCoolingEnergy; // J
    1971             :             }
    1972        5535 :             if ((UnitTotalCoolingRate - UnitSensibleCoolingRate) < 0) {
    1973        2395 :                 UnitLatentHeatingRate = UnitTotalHeatingRate - UnitSensibleHeatingRate;       // Watts
    1974        2395 :                 UnitLatentHeatingEnergy = UnitTotalHeatingEnergy - UnitSensibleHeatingEnergy; // J
    1975             :             }
    1976             : 
    1977             :             // set SYSTEM outputs
    1978        5535 :             if (QTotSystemOut > 0) // system cooling
    1979             :             {
    1980        3032 :                 SystemTotalCoolingRate = std::abs(QTotSystemOut);
    1981        3032 :                 SystemTotalCoolingEnergy = SystemTotalCoolingRate * state.dataHVACGlobal->TimeStepSysSec;
    1982             :             } else {
    1983        2503 :                 SystemTotalHeatingRate = std::abs(QTotSystemOut);
    1984        2503 :                 SystemTotalHeatingEnergy = SystemTotalHeatingRate * state.dataHVACGlobal->TimeStepSysSec;
    1985             :             }
    1986             : 
    1987        5535 :             if (QSensSystemOut > 0) // system sensible cooling
    1988             :             {
    1989        3030 :                 SystemSensibleCoolingRate = std::abs(QSensSystemOut);
    1990        3030 :                 SystemSensibleCoolingEnergy = SystemSensibleCoolingRate * state.dataHVACGlobal->TimeStepSysSec;
    1991             :             } else {
    1992        2505 :                 SystemSensibleHeatingRate = std::abs(QSensSystemOut);
    1993        2505 :                 SystemSensibleHeatingEnergy = SystemSensibleHeatingRate * state.dataHVACGlobal->TimeStepSysSec;
    1994             :             }
    1995        5535 :             if ((SystemTotalCoolingRate - SystemSensibleCoolingRate) > 0) {
    1996         408 :                 SystemLatentCoolingRate = SystemTotalCoolingRate - SystemSensibleCoolingRate;
    1997         408 :                 SystemLatentCoolingEnergy = SystemTotalCoolingEnergy - SystemSensibleCoolingEnergy;
    1998             :             }
    1999        5535 :             if ((SystemTotalHeatingRate - SystemSensibleHeatingRate) < 0) {
    2000        1472 :                 SystemLatentHeatingRate = SystemTotalHeatingRate - SystemSensibleHeatingRate;
    2001        1472 :                 SystemLatentHeatingEnergy = SystemTotalHeatingEnergy - SystemSensibleHeatingEnergy;
    2002             :             }
    2003             :         } else // unit is in standby so reset conditioning outputs
    2004             :         {
    2005        7740 :             QTotZoneOut = 0;
    2006        7740 :             QSensZoneOut = 0;
    2007        7740 :             QLatentZoneOut = 0;
    2008        7740 :             QLatentZoneOutMass = 0;
    2009        7740 :             QTotSystemOut = 0;
    2010        7740 :             QSensSystemOut = 0;
    2011        7740 :             QLatentSystemOut = 0;
    2012             :             // reset outputs
    2013        7740 :             ResetOutputs();
    2014             :         }
    2015             : 
    2016             :         // set timestep outputs calculated considering different runtime fractions.
    2017       13275 :         SupplyFanElectricPower = CalculateTimeStepAverage(SYSTEMOUTPUTS::OSUPPLY_FAN_POWER); // Watts
    2018       13275 :         SupplyFanElectricEnergy = SupplyFanElectricPower * state.dataHVACGlobal->TimeStepSysSec;
    2019       13275 :         SecondaryFuelConsumptionRate = CalculateTimeStepAverage(SYSTEMOUTPUTS::OSECOND_FUEL_USE);
    2020       13275 :         SecondaryFuelConsumption = SecondaryFuelConsumptionRate * state.dataHVACGlobal->TimeStepSysSec;
    2021       13275 :         ThirdFuelConsumptionRate = CalculateTimeStepAverage(SYSTEMOUTPUTS::OTHIRD_FUEL_USE);
    2022       13275 :         ThirdFuelConsumption = ThirdFuelConsumptionRate * state.dataHVACGlobal->TimeStepSysSec;
    2023       13275 :         WaterConsumptionRate = CalculateTimeStepAverage(SYSTEMOUTPUTS::OWATER_USE);
    2024       13275 :         WaterConsumption = WaterConsumptionRate * state.dataHVACGlobal->TimeStepSysSec;
    2025       13275 :         ExternalStaticPressure = CalculateTimeStepAverage(SYSTEMOUTPUTS::OEXTERNAL_STATIC_PRESSURE);
    2026             : 
    2027       13275 :         FinalElectricalPower = CalculateTimeStepAverage(SYSTEMOUTPUTS::SYSTEM_FUEL_USE);
    2028       13275 :         FinalElectricalEnergy = FinalElectricalPower * state.dataHVACGlobal->TimeStepSysSec;
    2029       13275 :     }
    2030             : 
    2031             : } // namespace HybridEvapCoolingModel
    2032             : } // namespace EnergyPlus

Generated by: LCOV version 1.14