LCOV - code coverage report
Current view: top level - EnergyPlus - HybridModel.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 6.1 % 198 12
Test Date: 2025-05-22 16:09:37 Functions: 100.0 % 1 1

            Line data    Source code
       1              : // EnergyPlus, Copyright (c) 1996-2025, The Board of Trustees of the University of Illinois,
       2              : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
       3              : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
       4              : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
       5              : // contributors. All rights reserved.
       6              : //
       7              : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
       8              : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
       9              : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
      10              : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
      11              : // derivative works, and perform publicly and display publicly, and to permit others to do so.
      12              : //
      13              : // Redistribution and use in source and binary forms, with or without modification, are permitted
      14              : // provided that the following conditions are met:
      15              : //
      16              : // (1) Redistributions of source code must retain the above copyright notice, this list of
      17              : //     conditions and the following disclaimer.
      18              : //
      19              : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
      20              : //     conditions and the following disclaimer in the documentation and/or other materials
      21              : //     provided with the distribution.
      22              : //
      23              : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
      24              : //     the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
      25              : //     used to endorse or promote products derived from this software without specific prior
      26              : //     written permission.
      27              : //
      28              : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
      29              : //     without changes from the version obtained under this License, or (ii) Licensee makes a
      30              : //     reference solely to the software portion of its product, Licensee must refer to the
      31              : //     software as "EnergyPlus version X" software, where "X" is the version number Licensee
      32              : //     obtained under this License and may not use a different name for the software. Except as
      33              : //     specifically required in this Section (4), Licensee shall not use in a company name, a
      34              : //     product name, in advertising, publicity, or other promotional activities any name, trade
      35              : //     name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
      36              : //     similar designation, without the U.S. Department of Energy's prior written consent.
      37              : //
      38              : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
      39              : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
      40              : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
      41              : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      42              : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
      43              : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      44              : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
      45              : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      46              : // POSSIBILITY OF SUCH DAMAGE.
      47              : 
      48              : // ObjexxFCL Headers
      49              : #include <ObjexxFCL/Array.functions.hh>
      50              : 
      51              : // EnergyPlus Headers
      52              : #include <EnergyPlus/Data/EnergyPlusData.hh>
      53              : #include <EnergyPlus/DataHeatBalance.hh>
      54              : #include <EnergyPlus/DataIPShortCuts.hh>
      55              : #include <EnergyPlus/DataRoomAirModel.hh>
      56              : #include <EnergyPlus/HeatBalanceManager.hh>
      57              : #include <EnergyPlus/HybridModel.hh>
      58              : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      59              : #include <EnergyPlus/OutputProcessor.hh>
      60              : #include <EnergyPlus/ScheduleManager.hh>
      61              : #include <EnergyPlus/UtilityRoutines.hh>
      62              : 
      63              : namespace EnergyPlus {
      64              : 
      65              : namespace HybridModel {
      66              : 
      67              :     // MODULE INFORMATION:
      68              :     //       AUTHOR         Sang Hoon Lee, Tianzhen Hong, Rongpeng Zhang. LBNL
      69              :     //       DATE WRITTEN   Oct 2015
      70              : 
      71              :     // PURPOSE OF THIS MODULE:
      72              :     // This module manages hybrid model.
      73              : 
      74              :     // METHODOLOGY EMPLOYED:
      75              :     //  The model uses measured zone air temperature to calculate internal thermal mass or infiltration air flow rate.
      76              : 
      77              :     // USE STATEMENTS:
      78              : 
      79              :     // Using/Aliasing
      80              :     using namespace DataHeatBalance;
      81              : 
      82              :     // Functions
      83              : 
      84          110 :     void GetHybridModelZone(EnergyPlusData &state)
      85              :     {
      86          110 :         Array1D_bool lAlphaFieldBlanks(16, false);
      87          110 :         Array1D_bool lNumericFieldBlanks(4, false);
      88          110 :         std::string CurrentModuleObject; // to assist in getting input
      89          110 :         Array1D_string cAlphaArgs(16);   // Alpha input items for object
      90          110 :         Array1D_string cAlphaFieldNames(16);
      91          110 :         Array1D_string cNumericFieldNames(16);
      92          110 :         Array1D<Real64> rNumericArgs(4); // Numeric input items for object
      93              : 
      94              :         // Read hybrid model input
      95          110 :         CurrentModuleObject = "HybridModel:Zone";
      96          110 :         state.dataHybridModel->NumOfHybridModelZones = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, CurrentModuleObject);
      97              : 
      98          110 :         if (state.dataHybridModel->NumOfHybridModelZones > 0) {
      99            0 :             state.dataHybridModel->hybridModelZones.allocate(state.dataGlobal->NumOfZones);
     100            0 :             bool ErrorsFound = false; // If errors detected in input
     101            0 :             int NumAlphas = 0;        // Number of Alphas for each GetobjectItem call
     102            0 :             int NumNumbers = 0;       // Number of Numbers for each GetobjectItem call
     103            0 :             int IOStatus = 0;
     104            0 :             int ZonePtr = 0;
     105            0 :             for (int HybridModelNum = 1; HybridModelNum <= state.dataHybridModel->NumOfHybridModelZones; ++HybridModelNum) {
     106              : 
     107            0 :                 state.dataInputProcessing->inputProcessor->getObjectItem(state,
     108              :                                                                          CurrentModuleObject,
     109              :                                                                          HybridModelNum,
     110              :                                                                          cAlphaArgs,
     111              :                                                                          NumAlphas,
     112              :                                                                          rNumericArgs,
     113              :                                                                          NumNumbers,
     114              :                                                                          IOStatus,
     115              :                                                                          lNumericFieldBlanks,
     116              :                                                                          lAlphaFieldBlanks,
     117              :                                                                          cAlphaFieldNames,
     118              :                                                                          cNumericFieldNames);
     119              : 
     120            0 :                 ZonePtr = Util::FindItemInList(cAlphaArgs(2), state.dataHeatBal->Zone); // "Zone" is a 1D array, cAlphaArgs(2) is the zone name
     121            0 :                 if (ZonePtr > 0) {
     122            0 :                     auto &hmZone = state.dataHybridModel->hybridModelZones(ZonePtr);
     123            0 :                     hmZone.Name = cAlphaArgs(1);                                                        // Zone HybridModel name
     124            0 :                     state.dataHybridModel->FlagHybridModel_TM = Util::SameString(cAlphaArgs(3), "Yes"); // Calculate thermal mass option
     125            0 :                     state.dataHybridModel->FlagHybridModel_AI = Util::SameString(cAlphaArgs(4), "Yes"); // Calculate infiltration rate option
     126            0 :                     state.dataHybridModel->FlagHybridModel_PC = Util::SameString(cAlphaArgs(5), "Yes"); // Calculate people count option
     127              : 
     128              :                     // Pointers used to help decide which unknown parameter to solve
     129              :                     // Zone Air Infiltration Rate and Zone Internal Thermal Mass calculations cannot be performed simultaneously
     130            0 :                     Sched::Schedule *temperatureSched = Sched::GetSchedule(state, cAlphaArgs(6));
     131            0 :                     Sched::Schedule *humidityRatioSched = Sched::GetSchedule(state, cAlphaArgs(7));
     132            0 :                     Sched::Schedule *CO2ConcentrationSched = Sched::GetSchedule(state, cAlphaArgs(8));
     133              : 
     134              :                     // Not used for now
     135            0 :                     Sched::Schedule *peopleActivityLevelSched = Sched::GetSchedule(state, cAlphaArgs(9));
     136            0 :                     Sched::Schedule *peopleSensibleFractionSched = Sched::GetSchedule(state, cAlphaArgs(10));
     137            0 :                     Sched::Schedule *peopleRadiantFractionSched = Sched::GetSchedule(state, cAlphaArgs(11));
     138            0 :                     Sched::Schedule *peopleCO2GenRateSched = Sched::GetSchedule(state, cAlphaArgs(12));
     139              : 
     140              :                     // Pointers used to help decide wheather to include system supply terms in the inverse algorithms
     141            0 :                     Sched::Schedule *supplyAirTemperatureSched = Sched::GetSchedule(state, cAlphaArgs(13));
     142            0 :                     Sched::Schedule *supplyAirMassFlowRateSched = Sched::GetSchedule(state, cAlphaArgs(14));
     143            0 :                     Sched::Schedule *supplyAirHumidityRatioSched = Sched::GetSchedule(state, cAlphaArgs(15));
     144            0 :                     Sched::Schedule *supplyAirCO2ConcentrationSched = Sched::GetSchedule(state, cAlphaArgs(16));
     145              : 
     146              :                     //  Note: Internal thermal mass can be calculated only with measured temperature.
     147              :                     //                  Air infiltration rate can be calculated with either measured temperature, humidity ratio, or CO2
     148              :                     //                  concentration. People count can be calculated with either measured temperature, humidity ratio, or CO2
     149              :                     //                  concentration.
     150              : 
     151              :                     // Initially set all flags to be false
     152            0 :                     hmZone.InternalThermalMassCalc_T = false;
     153            0 :                     hmZone.InfiltrationCalc_T = false;
     154            0 :                     hmZone.InfiltrationCalc_H = false;
     155            0 :                     hmZone.InfiltrationCalc_C = false;
     156            0 :                     hmZone.PeopleCountCalc_T = false;
     157            0 :                     hmZone.PeopleCountCalc_H = false;
     158            0 :                     hmZone.PeopleCountCalc_C = false;
     159              : 
     160              :                     // Scenario 1: Only one unknown parameter to solve
     161              :                     // Scenario 1-1: To solve thermal mass
     162            0 :                     if (state.dataHybridModel->FlagHybridModel_TM) {
     163            0 :                         if (state.dataHybridModel->FlagHybridModel_AI) {
     164            0 :                             ShowSevereError(state,
     165            0 :                                             format("Field \"{} and {}\" cannot be both set to YES.", cAlphaFieldNames(3), cAlphaFieldNames(4)));
     166            0 :                             ErrorsFound = true;
     167              :                         }
     168              : 
     169            0 :                         if (state.dataHybridModel->FlagHybridModel_PC) {
     170            0 :                             ShowSevereError(state,
     171            0 :                                             format("Field \"{} and {}\" cannot be both set to YES.", cAlphaFieldNames(3), cAlphaFieldNames(5)));
     172            0 :                             ErrorsFound = true;
     173              :                         }
     174              : 
     175            0 :                         if (temperatureSched == nullptr) {
     176            0 :                             ShowSevereError(state, format("Measured Zone Air Tempearture Schedule is not defined for: {}", CurrentModuleObject));
     177            0 :                             ErrorsFound = true;
     178              :                         } else {
     179            0 :                             hmZone.InternalThermalMassCalc_T = true;
     180              :                         }
     181              :                     }
     182              : 
     183              :                     // Scenario 1-2: To solve infiltration rate
     184            0 :                     if (state.dataHybridModel->FlagHybridModel_AI) {
     185            0 :                         if (state.dataHybridModel->FlagHybridModel_PC) {
     186            0 :                             ShowSevereError(state,
     187            0 :                                             format("Field \"{}\" and \"{}\" cannot be both set to YES.", cAlphaFieldNames(4), cAlphaFieldNames(5)));
     188            0 :                             ErrorsFound = true;
     189              :                         }
     190            0 :                         if (temperatureSched == nullptr && humidityRatioSched == nullptr && CO2ConcentrationSched == nullptr) {
     191              :                             // Show fatal error if no measurement schedule is provided
     192            0 :                             ShowSevereError(state, format("No measured environmental parameter is provided for: {}", CurrentModuleObject));
     193            0 :                             ShowContinueError(state,
     194            0 :                                               format("One of the field \"{}\", \"{}\", or {}\" must be provided for the HybridModel:Zone.",
     195              :                                                      cAlphaFieldNames(6),
     196              :                                                      cAlphaFieldNames(7),
     197              :                                                      cAlphaFieldNames(8)));
     198            0 :                             ErrorsFound = true;
     199              :                         } else {
     200            0 :                             if (temperatureSched != nullptr && !state.dataHybridModel->FlagHybridModel_TM) {
     201              :                                 // Temperature schedule is provided, igonore humidity ratio and CO2 concentration schedules.
     202            0 :                                 hmZone.InfiltrationCalc_T = true;
     203            0 :                                 if (humidityRatioSched != nullptr) {
     204            0 :                                     ShowWarningError(state, format("Field \"{}\" is provided.", cAlphaFieldNames(6)));
     205            0 :                                     ShowContinueError(state, format("Field \"{}\" will not be used.", cAlphaFieldNames(7)));
     206              :                                 }
     207            0 :                                 if (CO2ConcentrationSched != nullptr) {
     208            0 :                                     ShowWarningError(state, format("Field \"{}\" is provided.", cAlphaFieldNames(6)));
     209            0 :                                     ShowContinueError(state, format("Field \"{}\" will not be used.", cAlphaFieldNames(8)));
     210              :                                 }
     211              :                             }
     212            0 :                             if (humidityRatioSched != nullptr && temperatureSched == nullptr) {
     213              :                                 // Humidity ratio schedule is provided, ignore CO2 concentration schedule.
     214            0 :                                 hmZone.InfiltrationCalc_H = true;
     215            0 :                                 if (CO2ConcentrationSched != nullptr) {
     216            0 :                                     ShowWarningError(state, format("Field \"{}\" is provided.", cAlphaFieldNames(7)));
     217            0 :                                     ShowContinueError(state, format("Field \"{}\" will not be used.", cAlphaFieldNames(8)));
     218              :                                 }
     219              :                             }
     220            0 :                             if (CO2ConcentrationSched != nullptr && temperatureSched == nullptr && humidityRatioSched == nullptr) {
     221              :                                 // Only CO2 concentration schedule is provided.
     222            0 :                                 hmZone.InfiltrationCalc_C = true;
     223              :                             }
     224              :                         }
     225              :                     }
     226              : 
     227              :                     // Scenario 1-3: To solve people count
     228            0 :                     if (state.dataHybridModel->FlagHybridModel_PC) {
     229            0 :                         if (temperatureSched == nullptr && humidityRatioSched == nullptr && CO2ConcentrationSched == nullptr) {
     230              :                             // Show fatal error if no measurement schedule is provided
     231            0 :                             ShowSevereError(state, format("No measured environmental parameter is provided for: {}", CurrentModuleObject));
     232            0 :                             ShowContinueError(state,
     233            0 :                                               format("One of the field \"{}\", \"{}\", or {}\" must be provided for the HybridModel:Zone.",
     234              :                                                      cAlphaFieldNames(6),
     235              :                                                      cAlphaFieldNames(7),
     236              :                                                      cAlphaFieldNames(8)));
     237            0 :                             ErrorsFound = true;
     238              :                         } else {
     239            0 :                             if (temperatureSched != nullptr && !state.dataHybridModel->FlagHybridModel_TM) {
     240              :                                 // Temperature schedule is provided, igonore humidity ratio and CO2 concentration schedules.
     241            0 :                                 hmZone.PeopleCountCalc_T = true;
     242            0 :                                 if (humidityRatioSched != nullptr) {
     243            0 :                                     ShowWarningError(
     244              :                                         state,
     245              :                                         "The measured air humidity ratio schedule will not be used since measured air temperature is provided.");
     246              :                                 }
     247            0 :                                 if (CO2ConcentrationSched != nullptr) {
     248            0 :                                     ShowWarningError(
     249              :                                         state,
     250              :                                         "The measured air CO2 concentration schedule will not be used since measured air temperature is provided.");
     251              :                                 }
     252              :                             }
     253            0 :                             if (humidityRatioSched != nullptr && temperatureSched == nullptr) {
     254              :                                 // Humidity ratio schedule is provided, ignore CO2 concentration schedule.
     255            0 :                                 hmZone.PeopleCountCalc_H = true;
     256            0 :                                 if (CO2ConcentrationSched != nullptr) {
     257            0 :                                     ShowWarningError(state,
     258              :                                                      "The measured air CO2 concentration schedule will not be used since measured air humidity "
     259              :                                                      "ratio is provided.");
     260              :                                 }
     261              :                             }
     262            0 :                             if (CO2ConcentrationSched != nullptr && temperatureSched == nullptr && humidityRatioSched == nullptr) {
     263              :                                 // Only CO2 concentration schedule is provided.
     264            0 :                                 hmZone.PeopleCountCalc_C = true;
     265              :                             }
     266              :                         }
     267              :                     }
     268              : 
     269              :                     // Decide if system supply terms are valid to be included in the inverse solution
     270            0 :                     if (supplyAirTemperatureSched != nullptr && supplyAirMassFlowRateSched != nullptr && supplyAirHumidityRatioSched != nullptr) {
     271            0 :                         if (hmZone.InfiltrationCalc_T || hmZone.PeopleCountCalc_T) {
     272            0 :                             hmZone.IncludeSystemSupplyParameters = true;
     273              :                         } else {
     274            0 :                             ShowWarningError(state,
     275            0 :                                              format("Field \"{}\", {}, and \"{}\" will not be used in the inverse balance equation.",
     276              :                                                     cAlphaFieldNames(13),
     277              :                                                     cAlphaFieldNames(14),
     278              :                                                     cAlphaFieldNames(15)));
     279              :                         }
     280              :                     }
     281              : 
     282            0 :                     if (supplyAirHumidityRatioSched != nullptr && supplyAirMassFlowRateSched != nullptr) {
     283            0 :                         if (hmZone.InfiltrationCalc_H || hmZone.PeopleCountCalc_H) {
     284            0 :                             hmZone.IncludeSystemSupplyParameters = true;
     285              :                         } else {
     286            0 :                             ShowWarningError(state,
     287            0 :                                              format("Field \"{}\" and \"{}\" will not be used in the inverse balance equation.",
     288              :                                                     cAlphaFieldNames(15),
     289              :                                                     cAlphaFieldNames(14)));
     290              :                         }
     291              :                     }
     292              : 
     293            0 :                     if (supplyAirCO2ConcentrationSched != nullptr && supplyAirMassFlowRateSched != nullptr) {
     294            0 :                         if (hmZone.InfiltrationCalc_C || hmZone.PeopleCountCalc_C) {
     295            0 :                             hmZone.IncludeSystemSupplyParameters = true;
     296              :                         } else {
     297            0 :                             ShowWarningError(state,
     298            0 :                                              format("Field \"{}\" and \"{}\" will not be used in the inverse balance equation.",
     299              :                                                     cAlphaFieldNames(16),
     300              :                                                     cAlphaFieldNames(14)));
     301              :                         }
     302              :                     }
     303              : 
     304              :                     // Flags showing Hybrid Modeling settings
     305            0 :                     state.dataHybridModel->FlagHybridModel = hmZone.InternalThermalMassCalc_T || hmZone.InfiltrationCalc_T ||
     306            0 :                                                              hmZone.InfiltrationCalc_H || hmZone.InfiltrationCalc_C || hmZone.PeopleCountCalc_T ||
     307            0 :                                                              hmZone.PeopleCountCalc_H || hmZone.PeopleCountCalc_C;
     308              : 
     309            0 :                     if (hmZone.InternalThermalMassCalc_T || hmZone.InfiltrationCalc_T || hmZone.PeopleCountCalc_T) {
     310            0 :                         hmZone.measuredTempSched = temperatureSched;
     311              :                     }
     312              : 
     313            0 :                     if (hmZone.InfiltrationCalc_H || hmZone.PeopleCountCalc_H) {
     314            0 :                         hmZone.measuredHumRatSched = humidityRatioSched;
     315              :                     }
     316              : 
     317            0 :                     if (hmZone.InfiltrationCalc_C || hmZone.PeopleCountCalc_C) {
     318            0 :                         hmZone.measuredCO2ConcSched = CO2ConcentrationSched;
     319              :                     }
     320              : 
     321            0 :                     if (hmZone.IncludeSystemSupplyParameters) {
     322            0 :                         hmZone.supplyAirTempSched = supplyAirTemperatureSched;
     323            0 :                         hmZone.supplyAirMassFlowRateSched = supplyAirMassFlowRateSched;
     324            0 :                         hmZone.supplyAirHumRatSched = supplyAirHumidityRatioSched;
     325            0 :                         hmZone.supplyAirCO2ConcSched = supplyAirCO2ConcentrationSched;
     326              :                     }
     327              : 
     328              :                     // Get optional people related schedules
     329            0 :                     if (hmZone.PeopleCountCalc_T || hmZone.PeopleCountCalc_H || hmZone.PeopleCountCalc_C) {
     330            0 :                         if (peopleActivityLevelSched != nullptr) {
     331            0 :                             hmZone.peopleActivityLevelSched = peopleActivityLevelSched;
     332              :                         } else {
     333            0 :                             ShowWarningError(
     334              :                                 state,
     335            0 :                                 format("Field \"{}\": default people activity level is not provided, default value of 130W/person will be used.",
     336              :                                        cAlphaFieldNames(9)));
     337              :                         }
     338            0 :                         if (peopleSensibleFractionSched != nullptr) {
     339            0 :                             hmZone.peopleSensibleFracSched = peopleSensibleFractionSched;
     340              :                         } else {
     341            0 :                             ShowWarningError(
     342              :                                 state,
     343            0 :                                 format("Field \"{}\": default people sensible heat rate is not provided, default value of 0.6 will be used.",
     344              :                                        cAlphaFieldNames(10)));
     345              :                         }
     346            0 :                         if (peopleRadiantFractionSched != nullptr) {
     347            0 :                             hmZone.peopleRadiantFracSched = peopleRadiantFractionSched;
     348              :                         } else {
     349            0 :                             ShowWarningError(state,
     350            0 :                                              format("Field \"{}\": default people radiant heat portion (of sensible heat) is not provided, default "
     351              :                                                     "value of 0.7 will be used.",
     352              :                                                     cAlphaFieldNames(11)));
     353              :                         }
     354            0 :                         if (peopleCO2GenRateSched != nullptr) {
     355            0 :                             hmZone.peopleCO2GenRateSched = peopleCO2GenRateSched;
     356              :                         } else {
     357            0 :                             ShowWarningError(state,
     358            0 :                                              format("Field \"{}\": default people CO2 generation rate is not provided, default value of 0.0000000382 "
     359              :                                                     "kg/W will be used.",
     360              :                                                     cAlphaFieldNames(12)));
     361              :                         }
     362              :                     }
     363              : 
     364            0 :                     if (state.dataHybridModel->FlagHybridModel) {
     365              :                         // prepare start and end date for Hybrid Modeling
     366            0 :                         hmZone.measuredTempStartMonth = rNumericArgs(1);
     367            0 :                         hmZone.measuredTempStartDate = rNumericArgs(2);
     368            0 :                         hmZone.measuredTempEndMonth = rNumericArgs(3);
     369            0 :                         hmZone.measuredTempEndDate = rNumericArgs(4);
     370              :                         {
     371            0 :                             int const HMDayArr[12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
     372              : 
     373            0 :                             int HybridModelStartMonth = hmZone.measuredTempStartMonth;
     374            0 :                             int HybridModelStartDate = hmZone.measuredTempStartDate;
     375            0 :                             int HybridModelEndMonth = hmZone.measuredTempEndMonth;
     376            0 :                             int HybridModelEndDate = hmZone.measuredTempEndDate;
     377              : 
     378            0 :                             int HMStartDay = 0;
     379            0 :                             int HMEndDay = 0;
     380            0 :                             if (HybridModelStartMonth >= 1 && HybridModelStartMonth <= 12) {
     381            0 :                                 HMStartDay = HMDayArr[HybridModelStartMonth - 1];
     382              :                             }
     383              : 
     384            0 :                             if (HybridModelEndMonth >= 1 && HybridModelEndMonth <= 12) {
     385            0 :                                 HMEndDay = HMDayArr[HybridModelEndMonth - 1];
     386              :                             }
     387              : 
     388            0 :                             hmZone.HybridStartDayOfYear = HMStartDay + HybridModelStartDate;
     389            0 :                             hmZone.HybridEndDayOfYear = HMEndDay + HybridModelEndDate;
     390              :                         }
     391              :                     }
     392              : 
     393              :                     // Output variable
     394            0 :                     if (hmZone.InfiltrationCalc_T || hmZone.InfiltrationCalc_H || hmZone.InfiltrationCalc_C) {
     395            0 :                         SetupOutputVariable(state,
     396              :                                             "Zone Infiltration Hybrid Model Air Change Rate",
     397              :                                             Constant::Units::ach,
     398            0 :                                             state.dataHeatBal->Zone(ZonePtr).InfilOAAirChangeRateHM,
     399              :                                             OutputProcessor::TimeStepType::Zone,
     400              :                                             OutputProcessor::StoreType::Average,
     401            0 :                                             state.dataHeatBal->Zone(ZonePtr).Name);
     402            0 :                         SetupOutputVariable(state,
     403              :                                             "Zone Infiltration Hybrid Model Mass Flow Rate",
     404              :                                             Constant::Units::kg_s,
     405            0 :                                             state.dataHeatBal->Zone(ZonePtr).MCPIHM,
     406              :                                             OutputProcessor::TimeStepType::Zone,
     407              :                                             OutputProcessor::StoreType::Average,
     408            0 :                                             state.dataHeatBal->Zone(ZonePtr).Name);
     409              :                     }
     410            0 :                     if (hmZone.PeopleCountCalc_T || hmZone.PeopleCountCalc_H || hmZone.PeopleCountCalc_C) {
     411            0 :                         SetupOutputVariable(state,
     412              :                                             "Zone Hybrid Model People Count",
     413              :                                             Constant::Units::None,
     414            0 :                                             state.dataHeatBal->Zone(ZonePtr).NumOccHM,
     415              :                                             OutputProcessor::TimeStepType::Zone,
     416              :                                             OutputProcessor::StoreType::Average,
     417            0 :                                             state.dataHeatBal->Zone(ZonePtr).Name);
     418              :                     }
     419            0 :                     if (hmZone.InternalThermalMassCalc_T) {
     420            0 :                         SetupOutputVariable(state,
     421              :                                             "Zone Hybrid Model Thermal Mass Multiplier",
     422              :                                             Constant::Units::None,
     423            0 :                                             state.dataHeatBal->Zone(ZonePtr).ZoneVolCapMultpSensHM,
     424              :                                             OutputProcessor::TimeStepType::Zone,
     425              :                                             OutputProcessor::StoreType::Average,
     426            0 :                                             state.dataHeatBal->Zone(ZonePtr).Name);
     427              :                     }
     428              : 
     429              :                     // ZoneAirMassFlowConservation should not be activated during the Hybrid Modeling infiltration calculations
     430            0 :                     if (hmZone.InfiltrationCalc_T && state.dataHeatBal->ZoneAirMassFlow.EnforceZoneMassBalance) {
     431            0 :                         state.dataHeatBal->ZoneAirMassFlow.EnforceZoneMassBalance = false;
     432            0 :                         ShowWarningError(state, "ZoneAirMassFlowConservation is deactivated when Hybrid Modeling is performed.");
     433              :                     }
     434              :                 } else {
     435            0 :                     ShowSevereError(
     436              :                         state,
     437            0 :                         format("{}=\"{}\" invalid {}=\"{}\" not found.", CurrentModuleObject, cAlphaArgs(1), cAlphaFieldNames(2), cAlphaArgs(2)));
     438            0 :                     ErrorsFound = true;
     439              :                 }
     440              :             }
     441              : 
     442              :             // RoomAirModelType should be Mixing if Hybrid Modeling is performed for the zone
     443            0 :             if (state.dataHybridModel->FlagHybridModel) {
     444            0 :                 for (int ZonePtr = 1; ZonePtr <= state.dataGlobal->NumOfZones; ZonePtr++) {
     445            0 :                     auto &hmZone = state.dataHybridModel->hybridModelZones(ZonePtr);
     446            0 :                     if ((hmZone.InternalThermalMassCalc_T || hmZone.InfiltrationCalc_T) &&
     447            0 :                         (state.dataRoomAir->AirModel(ZonePtr).AirModel != RoomAir::RoomAirModel::Mixing)) {
     448            0 :                         state.dataRoomAir->AirModel(ZonePtr).AirModel = RoomAir::RoomAirModel::Mixing;
     449            0 :                         ShowWarningError(state, "Room Air Model Type should be Mixing if Hybrid Modeling is performed for the zone.");
     450              :                     }
     451              :                 }
     452            0 :                 if (state.dataHeatBal->doSpaceHeatBalanceSimulation || state.dataHeatBal->doSpaceHeatBalanceSizing) {
     453            0 :                     ShowSevereError(state, "Hybrid Modeling is not supported with ZoneAirHeatBalanceAlgorithm Space Heat Balance.");
     454            0 :                     ErrorsFound = true;
     455              :                 }
     456              :             }
     457              : 
     458            0 :             if (ErrorsFound) {
     459            0 :                 ShowFatalError(state, "Errors getting Hybrid Model input data. Preceding condition(s) cause termination.");
     460              :             }
     461              :         }
     462          110 :     }
     463              : 
     464              :     // Needed for unit tests, should not be normally called.
     465              : 
     466              : } // namespace HybridModel
     467              : 
     468              : } // namespace EnergyPlus
        

Generated by: LCOV version 2.0-1