LCOV - code coverage report
Current view: top level - EnergyPlus - HighTempRadiantSystem.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 348 561 62.0 %
Date: 2024-08-24 18:31:18 Functions: 10 10 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 <cassert>
      50             : #include <cmath>
      51             : 
      52             : // ObjexxFCL Headers
      53             : #include <ObjexxFCL/Array.functions.hh>
      54             : 
      55             : // EnergyPlus Headers
      56             : #include <EnergyPlus/Autosizing/HeatingCapacitySizing.hh>
      57             : #include <EnergyPlus/Data/EnergyPlusData.hh>
      58             : #include <EnergyPlus/DataGlobalConstants.hh>
      59             : #include <EnergyPlus/DataHVACGlobals.hh>
      60             : #include <EnergyPlus/DataHeatBalFanSys.hh>
      61             : #include <EnergyPlus/DataHeatBalSurface.hh>
      62             : #include <EnergyPlus/DataHeatBalance.hh>
      63             : #include <EnergyPlus/DataIPShortCuts.hh>
      64             : #include <EnergyPlus/DataSurfaces.hh>
      65             : #include <EnergyPlus/DataViewFactorInformation.hh>
      66             : #include <EnergyPlus/DataZoneEquipment.hh>
      67             : #include <EnergyPlus/General.hh>
      68             : #include <EnergyPlus/GeneralRoutines.hh>
      69             : #include <EnergyPlus/HeatBalanceIntRadExchange.hh>
      70             : #include <EnergyPlus/HeatBalanceSurfaceManager.hh>
      71             : #include <EnergyPlus/HighTempRadiantSystem.hh>
      72             : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      73             : #include <EnergyPlus/OutputProcessor.hh>
      74             : #include <EnergyPlus/ScheduleManager.hh>
      75             : #include <EnergyPlus/UtilityRoutines.hh>
      76             : #include <EnergyPlus/ZoneTempPredictorCorrector.hh>
      77             : 
      78             : namespace EnergyPlus {
      79             : 
      80             : namespace HighTempRadiantSystem {
      81             : 
      82             :     // Module containing the routines dealing with the high temperature radiant systems
      83             : 
      84             :     // MODULE INFORMATION:
      85             :     //       AUTHOR         Rick Strand
      86             :     //       DATE WRITTEN   February 2001
      87             : 
      88             :     // PURPOSE OF THIS MODULE:
      89             :     // The purpose of this module is to simulate high temperature radiant systems.
      90             :     // It is the intention of this module to cover all types of high temperature
      91             :     // radiant systems (gas and electric)
      92             : 
      93             :     // METHODOLOGY EMPLOYED:
      94             :     // Based on work done in BLAST, the EnergyPlus low temperature radiant system
      95             :     // model, this model has similar inherent challenges that are similar to the
      96             :     // low temperature radiant system.  Because it is a system that directly
      97             :     // effects the surface heat balances, it must be a part of both the heat
      98             :     // balance routines and linked in with the HVAC system.
      99             :     // REFERENCES:
     100             :     // Building Systems Laboratory, BLAST User's Guide/Reference.
     101             :     // Maloney, Dan. 1987. "Development of a radiant heater model and the
     102             :     //   incorporation of thermal comfort considerations into the BLAST
     103             :     //   energy analysis program", M.S. thesis, University of Illinois at
     104             :     //   Urbana-Champaign (Dept. of Mechanical and Industrial Engineering).
     105             : 
     106             :     // MODULE PARAMETER DEFINITIONS:
     107             :     constexpr std::array<std::string_view, static_cast<int>(RadControlType::Num)> radControlTypeNamesUC = {"MEANAIRTEMPERATURE",
     108             :                                                                                                            "MEANRADIANTTEMPERATURE",
     109             :                                                                                                            "OPERATIVETEMPERATURE",
     110             :                                                                                                            "MEANAIRTEMPERATURESETPOINT",
     111             :                                                                                                            "MEANRADIANTTEMPERATURESETPOINT",
     112             :                                                                                                            "OPERATIVETEMPERATURESETPOINT"};
     113             : 
     114      129408 :     void SimHighTempRadiantSystem(EnergyPlusData &state,
     115             :                                   std::string_view CompName,     // name of the low temperature radiant system
     116             :                                   bool const FirstHVACIteration, // TRUE if 1st HVAC simulation of system timestep
     117             :                                   Real64 &LoadMet,               // load met by the radiant system, in Watts
     118             :                                   int &CompIndex)
     119             :     {
     120             : 
     121             :         // SUBROUTINE INFORMATION:
     122             :         //       AUTHOR         Rick Strand
     123             :         //       DATE WRITTEN   February 2001
     124             : 
     125             :         // PURPOSE OF THIS SUBROUTINE:
     126             :         // This subroutine is the "manager" for the high temperature radiant
     127             :         // system model.  It is called from the outside and controls the
     128             :         // actions and subroutine calls to lower levels as appropriate.
     129             : 
     130             :         // METHODOLOGY EMPLOYED:
     131             :         // Standard EnergyPlus manager subroutine layout
     132             : 
     133             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     134             :         int RadSysNum; // Radiant system number/index in local derived types
     135             : 
     136      129408 :         if (state.dataHighTempRadSys->GetInputFlag) {
     137           4 :             bool ErrorsFoundInGet = false;
     138           4 :             GetHighTempRadiantSystem(state, ErrorsFoundInGet);
     139           4 :             if (ErrorsFoundInGet)
     140           0 :                 ShowFatalError(state, "GetHighTempRadiantSystem: Errors found in input.  Preceding condition(s) cause termination.");
     141           4 :             state.dataHighTempRadSys->GetInputFlag = false;
     142             :         }
     143             : 
     144             :         // Find the correct ZoneHVAC:HighTemperatureRadiant
     145      129408 :         if (CompIndex == 0) {
     146          10 :             RadSysNum = Util::FindItemInList(CompName, state.dataHighTempRadSys->HighTempRadSys);
     147          10 :             if (RadSysNum == 0) {
     148           0 :                 ShowFatalError(state, format("SimHighTempRadiantSystem: Unit not found={}", CompName));
     149             :             }
     150          10 :             CompIndex = RadSysNum;
     151             :         } else {
     152      129398 :             RadSysNum = CompIndex;
     153      129398 :             if (RadSysNum > state.dataHighTempRadSys->NumOfHighTempRadSys || RadSysNum < 1) {
     154           0 :                 ShowFatalError(state,
     155           0 :                                format("SimHighTempRadiantSystem:  Invalid CompIndex passed={}, Number of Units={}, Entered Unit name={}",
     156             :                                       RadSysNum,
     157           0 :                                       state.dataHighTempRadSys->NumOfHighTempRadSys,
     158             :                                       CompName));
     159             :             }
     160      129398 :             if (state.dataHighTempRadSys->CheckEquipName(RadSysNum)) {
     161          10 :                 if (CompName != state.dataHighTempRadSys->HighTempRadSys(RadSysNum).Name) {
     162           0 :                     ShowFatalError(state,
     163           0 :                                    format("SimHighTempRadiantSystem: Invalid CompIndex passed={}, Unit name={}, stored Unit Name for that index={}",
     164             :                                           RadSysNum,
     165             :                                           CompName,
     166           0 :                                           state.dataHighTempRadSys->HighTempRadSys(RadSysNum).Name));
     167             :                 }
     168          10 :                 state.dataHighTempRadSys->CheckEquipName(RadSysNum) = false;
     169             :             }
     170             :         }
     171             : 
     172      129408 :         InitHighTempRadiantSystem(state, FirstHVACIteration, RadSysNum);
     173             : 
     174      129408 :         switch (state.dataHighTempRadSys->HighTempRadSys(RadSysNum).ControlType) {
     175       44259 :         case RadControlType::MATControl:
     176             :         case RadControlType::MRTControl:
     177             :         case RadControlType::OperativeControl: {
     178       44259 :             CalcHighTempRadiantSystem(state, RadSysNum);
     179       44259 :         } break;
     180       85149 :         case RadControlType::MATSPControl:
     181             :         case RadControlType::MRTSPControl:
     182             :         case RadControlType::OperativeSPControl: {
     183       85149 :             CalcHighTempRadiantSystemSP(state, FirstHVACIteration, RadSysNum);
     184       85149 :         } break;
     185           0 :         default:
     186           0 :             break;
     187             :         }
     188             : 
     189      129408 :         UpdateHighTempRadiantSystem(state, RadSysNum, LoadMet);
     190             : 
     191      129408 :         ReportHighTempRadiantSystem(state, RadSysNum);
     192      129408 :     }
     193             : 
     194           4 :     void GetHighTempRadiantSystem(EnergyPlusData &state, bool &ErrorsFound // TRUE if errors are found on processing the input
     195             :     )
     196             :     {
     197             : 
     198             :         // SUBROUTINE INFORMATION:
     199             :         //       AUTHOR         Rick Strand
     200             :         //       DATE WRITTEN   February 2001
     201             : 
     202             :         // PURPOSE OF THIS SUBROUTINE:
     203             :         // This subroutine reads the input for high temperature radiant systems
     204             :         // from the user input file.  This will contain all of the information
     205             :         // needed to simulate a high temperature radiant system.
     206             : 
     207             :         // METHODOLOGY EMPLOYED:
     208             :         // Standard EnergyPlus methodology.
     209             : 
     210             :         // SUBROUTINE PARAMETER DEFINITIONS:
     211           4 :         Real64 constexpr MaxCombustionEffic = 1.0;                // Limit the combustion efficiency to perfection
     212           4 :         Real64 constexpr MaxFraction = 1.0;                       // Limit the highest allowed fraction for heat transfer parts
     213           4 :         Real64 constexpr MinCombustionEffic = 0.01;               // Limit the minimum combustion efficiency
     214           4 :         Real64 constexpr MinFraction = 0.0;                       // Limit the lowest allowed fraction for heat transfer parts
     215           4 :         Real64 constexpr MinThrottlingRange = 0.5;                // Smallest throttling range allowed in degrees Celsius
     216           4 :         int constexpr iHeatCAPMAlphaNum = 4;                      // get input index to High Temperature Radiant system heating capacity sizing method
     217           4 :         int constexpr iHeatDesignCapacityNumericNum = 1;          // get input index to High Temperature Radiant system heating capacity
     218           4 :         int constexpr iHeatCapacityPerFloorAreaNumericNum = 2;    // index to High Temperature Radiant system heating capacity per floor area sizing
     219           4 :         int constexpr iHeatFracOfAutosizedCapacityNumericNum = 3; // index to system capacity sizing as fraction of autozized heating capacity
     220             : 
     221             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     222             :         Real64 FracOfRadPotentiallyLost; // Difference between unity and AllFracsSummed for error reporting
     223             :         int IOStatus;                    // Used in GetObjectItem
     224             :         int NumAlphas;                   // Number of Alphas for each GetObjectItem call
     225             :         int NumNumbers;                  // Number of Numbers for each GetObjectItem call
     226             : 
     227             :         // Initializations and allocations
     228           8 :         state.dataHighTempRadSys->NumOfHighTempRadSys =
     229           4 :             state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "ZoneHVAC:HighTemperatureRadiant");
     230             : 
     231           4 :         state.dataHighTempRadSys->HighTempRadSys.allocate(state.dataHighTempRadSys->NumOfHighTempRadSys);
     232           4 :         state.dataHighTempRadSys->CheckEquipName.allocate(state.dataHighTempRadSys->NumOfHighTempRadSys);
     233           4 :         state.dataHighTempRadSys->HighTempRadSysNumericFields.allocate(state.dataHighTempRadSys->NumOfHighTempRadSys);
     234           4 :         state.dataHighTempRadSys->CheckEquipName = true;
     235             : 
     236             :         // extensible object, do not need max args because using IPShortCuts
     237           4 :         auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
     238           4 :         cCurrentModuleObject = "ZoneHVAC:HighTemperatureRadiant";
     239             :         // Obtain all of the user data related to high temperature radiant systems...
     240          14 :         for (int Item = 1; Item <= state.dataHighTempRadSys->NumOfHighTempRadSys; ++Item) {
     241          10 :             auto &highTempRadSys = state.dataHighTempRadSys->HighTempRadSys(Item);
     242             : 
     243          20 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
     244             :                                                                      cCurrentModuleObject,
     245             :                                                                      Item,
     246          10 :                                                                      state.dataIPShortCut->cAlphaArgs,
     247             :                                                                      NumAlphas,
     248          10 :                                                                      state.dataIPShortCut->rNumericArgs,
     249             :                                                                      NumNumbers,
     250             :                                                                      IOStatus,
     251          10 :                                                                      state.dataIPShortCut->lNumericFieldBlanks,
     252          10 :                                                                      state.dataIPShortCut->lAlphaFieldBlanks,
     253          10 :                                                                      state.dataIPShortCut->cAlphaFieldNames,
     254          10 :                                                                      state.dataIPShortCut->cNumericFieldNames);
     255             : 
     256          10 :             state.dataHighTempRadSys->HighTempRadSysNumericFields(Item).FieldNames.allocate(NumNumbers);
     257          10 :             state.dataHighTempRadSys->HighTempRadSysNumericFields(Item).FieldNames = "";
     258          10 :             state.dataHighTempRadSys->HighTempRadSysNumericFields(Item).FieldNames = state.dataIPShortCut->cNumericFieldNames;
     259             :             // General user input data
     260          10 :             highTempRadSys.Name = state.dataIPShortCut->cAlphaArgs(1);
     261             : 
     262          10 :             highTempRadSys.SchedName = state.dataIPShortCut->cAlphaArgs(2);
     263          10 :             if (state.dataIPShortCut->lAlphaFieldBlanks(2)) {
     264           0 :                 highTempRadSys.SchedPtr = ScheduleManager::ScheduleAlwaysOn;
     265             :             } else {
     266          10 :                 highTempRadSys.SchedPtr = ScheduleManager::GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(2));
     267          10 :                 if (highTempRadSys.SchedPtr == 0) {
     268           0 :                     ShowSevereError(state,
     269           0 :                                     format("{}: invalid {} entered ={} for {} = {}",
     270             :                                            cCurrentModuleObject,
     271           0 :                                            state.dataIPShortCut->cAlphaFieldNames(2),
     272           0 :                                            state.dataIPShortCut->cAlphaArgs(2),
     273           0 :                                            state.dataIPShortCut->cAlphaFieldNames(1),
     274           0 :                                            state.dataIPShortCut->cAlphaArgs(1)));
     275           0 :                     ErrorsFound = true;
     276             :                 }
     277             :             }
     278             : 
     279          10 :             highTempRadSys.ZonePtr = Util::FindItemInList(state.dataIPShortCut->cAlphaArgs(3), state.dataHeatBal->Zone);
     280          10 :             if (highTempRadSys.ZonePtr == 0) {
     281           0 :                 ShowSevereError(state, format("Invalid {} = {}", state.dataIPShortCut->cAlphaFieldNames(3), state.dataIPShortCut->cAlphaArgs(3)));
     282           0 :                 ShowContinueError(state, format("Occurs for {} = {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
     283           0 :                 ErrorsFound = true;
     284             :             }
     285             : 
     286             :             // state.dataHighTempRadSys->HighTempRadSys( Item ).MaxPowerCapac = state.dataIPShortCut->rNumericArgs( 1 );
     287             : 
     288             :             // Determine High Temp Radiant heating design capacity sizing method
     289          10 :             highTempRadSys.HeatingCapMethod = static_cast<DataSizing::DesignSizingType>(
     290          10 :                 getEnumValue(DataSizing::DesignSizingTypeNamesUC, state.dataIPShortCut->cAlphaArgs(iHeatCAPMAlphaNum)));
     291          10 :             if (highTempRadSys.HeatingCapMethod == DataSizing::DesignSizingType::HeatingDesignCapacity) {
     292          10 :                 if (!state.dataIPShortCut->lNumericFieldBlanks(iHeatDesignCapacityNumericNum)) {
     293          10 :                     highTempRadSys.ScaledHeatingCapacity = state.dataIPShortCut->rNumericArgs(iHeatDesignCapacityNumericNum);
     294          10 :                     if (highTempRadSys.ScaledHeatingCapacity < 0.0 && highTempRadSys.ScaledHeatingCapacity != DataSizing::AutoSize) {
     295           0 :                         ShowSevereError(state, format("{} = {}", cCurrentModuleObject, highTempRadSys.Name));
     296           0 :                         ShowContinueError(state,
     297           0 :                                           format("Illegal {} = {:.7T}",
     298           0 :                                                  state.dataIPShortCut->cNumericFieldNames(iHeatDesignCapacityNumericNum),
     299           0 :                                                  state.dataIPShortCut->rNumericArgs(iHeatDesignCapacityNumericNum)));
     300           0 :                         ErrorsFound = true;
     301             :                     }
     302             :                 } else {
     303           0 :                     ShowSevereError(state, format("{} = {}", cCurrentModuleObject, highTempRadSys.Name));
     304           0 :                     ShowContinueError(state,
     305           0 :                                       format("Input for {} = {}",
     306           0 :                                              state.dataIPShortCut->cAlphaFieldNames(iHeatCAPMAlphaNum),
     307           0 :                                              state.dataIPShortCut->cAlphaArgs(iHeatCAPMAlphaNum)));
     308           0 :                     ShowContinueError(
     309           0 :                         state, format("Blank field not allowed for {}", state.dataIPShortCut->cNumericFieldNames(iHeatDesignCapacityNumericNum)));
     310           0 :                     ErrorsFound = true;
     311             :                 }
     312           0 :             } else if (highTempRadSys.HeatingCapMethod == DataSizing::DesignSizingType::CapacityPerFloorArea) {
     313           0 :                 if (!state.dataIPShortCut->lNumericFieldBlanks(iHeatCapacityPerFloorAreaNumericNum)) {
     314           0 :                     highTempRadSys.ScaledHeatingCapacity = state.dataIPShortCut->rNumericArgs(iHeatCapacityPerFloorAreaNumericNum);
     315           0 :                     if (highTempRadSys.ScaledHeatingCapacity <= 0.0) {
     316           0 :                         ShowSevereError(state, format("{} = {}", cCurrentModuleObject, highTempRadSys.Name));
     317           0 :                         ShowContinueError(state,
     318           0 :                                           format("Input for {} = {}",
     319           0 :                                                  state.dataIPShortCut->cAlphaFieldNames(iHeatCAPMAlphaNum),
     320           0 :                                                  state.dataIPShortCut->cAlphaArgs(iHeatCAPMAlphaNum)));
     321           0 :                         ShowContinueError(state,
     322           0 :                                           format("Illegal {} = {:.7T}",
     323           0 :                                                  state.dataIPShortCut->cNumericFieldNames(iHeatCapacityPerFloorAreaNumericNum),
     324           0 :                                                  state.dataIPShortCut->rNumericArgs(iHeatCapacityPerFloorAreaNumericNum)));
     325           0 :                         ErrorsFound = true;
     326           0 :                     } else if (highTempRadSys.ScaledHeatingCapacity == DataSizing::AutoSize) {
     327           0 :                         ShowSevereError(state, format("{} = {}", cCurrentModuleObject, highTempRadSys.Name));
     328           0 :                         ShowContinueError(state,
     329           0 :                                           format("Input for {} = {}",
     330           0 :                                                  state.dataIPShortCut->cAlphaFieldNames(iHeatCAPMAlphaNum),
     331           0 :                                                  state.dataIPShortCut->cAlphaArgs(iHeatCAPMAlphaNum)));
     332           0 :                         ShowContinueError(
     333           0 :                             state, format("Illegal {} = Autosize", state.dataIPShortCut->cNumericFieldNames(iHeatCapacityPerFloorAreaNumericNum)));
     334           0 :                         ErrorsFound = true;
     335             :                     }
     336             :                 } else {
     337           0 :                     ShowSevereError(state, format("{} = {}", cCurrentModuleObject, highTempRadSys.Name));
     338           0 :                     ShowContinueError(state,
     339           0 :                                       format("Input for {} = {}",
     340           0 :                                              state.dataIPShortCut->cAlphaFieldNames(iHeatCAPMAlphaNum),
     341           0 :                                              state.dataIPShortCut->cAlphaArgs(iHeatCAPMAlphaNum)));
     342           0 :                     ShowContinueError(
     343             :                         state,
     344           0 :                         format("Blank field not allowed for {}", state.dataIPShortCut->cNumericFieldNames(iHeatCapacityPerFloorAreaNumericNum)));
     345           0 :                     ErrorsFound = true;
     346             :                 }
     347           0 :             } else if (highTempRadSys.HeatingCapMethod == DataSizing::DesignSizingType::FractionOfAutosizedHeatingCapacity) {
     348           0 :                 if (!state.dataIPShortCut->lNumericFieldBlanks(iHeatFracOfAutosizedCapacityNumericNum)) {
     349           0 :                     highTempRadSys.ScaledHeatingCapacity = state.dataIPShortCut->rNumericArgs(iHeatFracOfAutosizedCapacityNumericNum);
     350           0 :                     if (highTempRadSys.ScaledHeatingCapacity < 0.0) {
     351           0 :                         ShowSevereError(state, format("{} = {}", cCurrentModuleObject, highTempRadSys.Name));
     352           0 :                         ShowContinueError(state,
     353           0 :                                           format("Illegal {} = {:.7T}",
     354           0 :                                                  state.dataIPShortCut->cNumericFieldNames(iHeatFracOfAutosizedCapacityNumericNum),
     355           0 :                                                  state.dataIPShortCut->rNumericArgs(iHeatFracOfAutosizedCapacityNumericNum)));
     356           0 :                         ErrorsFound = true;
     357             :                     }
     358             :                 } else {
     359           0 :                     ShowSevereError(state, format("{} = {}", cCurrentModuleObject, highTempRadSys.Name));
     360           0 :                     ShowContinueError(state,
     361           0 :                                       format("Input for {} = {}",
     362           0 :                                              state.dataIPShortCut->cAlphaFieldNames(iHeatCAPMAlphaNum),
     363           0 :                                              state.dataIPShortCut->cAlphaArgs(iHeatCAPMAlphaNum)));
     364           0 :                     ShowContinueError(
     365             :                         state,
     366           0 :                         format("Blank field not allowed for {}", state.dataIPShortCut->cNumericFieldNames(iHeatFracOfAutosizedCapacityNumericNum)));
     367           0 :                     ErrorsFound = true;
     368             :                 }
     369             :             }
     370             : 
     371          10 :             highTempRadSys.HeaterType =
     372          10 :                 static_cast<Constant::eResource>(getEnumValue(Constant::eResourceNamesUC, state.dataIPShortCut->cAlphaArgs(5)));
     373             : 
     374          10 :             if (highTempRadSys.HeaterType == Constant::eResource::NaturalGas) {
     375           7 :                 highTempRadSys.CombustionEffic = state.dataIPShortCut->rNumericArgs(4);
     376             :                 // Limit the combustion efficiency to between zero and one...
     377           7 :                 if (highTempRadSys.CombustionEffic < MinCombustionEffic) {
     378           0 :                     highTempRadSys.CombustionEffic = MinCombustionEffic;
     379           0 :                     ShowWarningError(
     380             :                         state,
     381           0 :                         format("{} was less than the allowable minimum, reset to minimum value.", state.dataIPShortCut->cNumericFieldNames(4)));
     382           0 :                     ShowContinueError(state, format("Occurs for {} = {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
     383             :                 }
     384           7 :                 if (highTempRadSys.CombustionEffic > MaxCombustionEffic) {
     385           0 :                     highTempRadSys.CombustionEffic = MaxCombustionEffic;
     386           0 :                     ShowWarningError(
     387             :                         state,
     388           0 :                         format("{} was greater than the allowable maximum, reset to maximum value.", state.dataIPShortCut->cNumericFieldNames(4)));
     389           0 :                     ShowContinueError(state, format("Occurs for {} = {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
     390             :                 }
     391             :             } else {
     392           3 :                 highTempRadSys.CombustionEffic = MaxCombustionEffic; // No inefficiency in the heater
     393             :             }
     394             : 
     395          10 :             highTempRadSys.FracRadiant = state.dataIPShortCut->rNumericArgs(5);
     396          10 :             if (highTempRadSys.FracRadiant < MinFraction) {
     397           0 :                 highTempRadSys.FracRadiant = MinFraction;
     398           0 :                 ShowWarningError(
     399           0 :                     state, format("{} was less than the allowable minimum, reset to minimum value.", state.dataIPShortCut->cNumericFieldNames(5)));
     400           0 :                 ShowContinueError(state, format("Occurs for {} = {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
     401             :             }
     402          10 :             if (highTempRadSys.FracRadiant > MaxFraction) {
     403           0 :                 highTempRadSys.FracRadiant = MaxFraction;
     404           0 :                 ShowWarningError(
     405           0 :                     state, format("{} was greater than the allowable maximum, reset to maximum value.", state.dataIPShortCut->cNumericFieldNames(5)));
     406           0 :                 ShowContinueError(state, format("Occurs for {} = {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
     407             :             }
     408             : 
     409          10 :             highTempRadSys.FracLatent = state.dataIPShortCut->rNumericArgs(6);
     410          10 :             if (highTempRadSys.FracLatent < MinFraction) {
     411           0 :                 highTempRadSys.FracLatent = MinFraction;
     412           0 :                 ShowWarningError(
     413           0 :                     state, format("{} was less than the allowable minimum, reset to minimum value.", state.dataIPShortCut->cNumericFieldNames(6)));
     414           0 :                 ShowContinueError(state, format("Occurs for {} = {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
     415             :             }
     416          10 :             if (highTempRadSys.FracLatent > MaxFraction) {
     417           0 :                 highTempRadSys.FracLatent = MaxFraction;
     418           0 :                 ShowWarningError(
     419           0 :                     state, format("{} was greater than the allowable maximum, reset to maximum value.", state.dataIPShortCut->cNumericFieldNames(6)));
     420           0 :                 ShowContinueError(state, format("Occurs for {} = {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
     421             :             }
     422             : 
     423          10 :             highTempRadSys.FracLost = state.dataIPShortCut->rNumericArgs(7);
     424          10 :             if (highTempRadSys.FracLost < MinFraction) {
     425           0 :                 highTempRadSys.FracLost = MinFraction;
     426           0 :                 ShowWarningError(
     427           0 :                     state, format("{} was less than the allowable minimum, reset to minimum value.", state.dataIPShortCut->cNumericFieldNames(7)));
     428           0 :                 ShowContinueError(state, format("Occurs for {} = {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
     429             :             }
     430          10 :             if (highTempRadSys.FracLost > MaxFraction) {
     431           0 :                 highTempRadSys.FracLost = MaxFraction;
     432           0 :                 ShowWarningError(
     433           0 :                     state, format("{} was greater than the allowable maximum, reset to maximum value.", state.dataIPShortCut->cNumericFieldNames(7)));
     434           0 :                 ShowContinueError(state, format("Occurs for {} = {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
     435             :             }
     436             : 
     437             :             // Based on the input for fractions radiant, latent, and lost, determine the fraction convective (remaining fraction)
     438          10 :             Real64 AllFracsSummed = highTempRadSys.FracRadiant + highTempRadSys.FracLatent + highTempRadSys.FracLost;
     439          10 :             if (AllFracsSummed > MaxFraction) {
     440           0 :                 ShowSevereError(state,
     441           0 :                                 format("Fractions radiant, latent, and lost sum up to greater than 1 for{}", state.dataIPShortCut->cAlphaArgs(1)));
     442           0 :                 ShowContinueError(state, format("Occurs for {} = {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
     443           0 :                 ErrorsFound = true;
     444           0 :                 highTempRadSys.FracConvect = 0.0;
     445             :             } else {
     446          10 :                 highTempRadSys.FracConvect = 1.0 - AllFracsSummed;
     447             :             }
     448             : 
     449             :             // Process the temperature control type
     450          10 :             highTempRadSys.ControlType = static_cast<RadControlType>(getEnumValue(radControlTypeNamesUC, state.dataIPShortCut->cAlphaArgs(6)));
     451             : 
     452          10 :             highTempRadSys.ThrottlRange = state.dataIPShortCut->rNumericArgs(8);
     453          10 :             if (highTempRadSys.ThrottlRange < MinThrottlingRange) {
     454           0 :                 highTempRadSys.ThrottlRange = 1.0;
     455           0 :                 ShowWarningError(state, format("{} is below the minimum allowed.", state.dataIPShortCut->cNumericFieldNames(8)));
     456           0 :                 ShowContinueError(state, format("Occurs for {} = {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
     457           0 :                 ShowContinueError(state, "Thus, the throttling range value has been reset to 1.0");
     458             :             }
     459             : 
     460          10 :             highTempRadSys.SetptSched = state.dataIPShortCut->cAlphaArgs(7);
     461          10 :             highTempRadSys.SetptSchedPtr = ScheduleManager::GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(7));
     462          10 :             if ((highTempRadSys.SetptSchedPtr == 0) && (!state.dataIPShortCut->lAlphaFieldBlanks(7))) {
     463           0 :                 ShowSevereError(state, format("{} not found: {}", state.dataIPShortCut->cAlphaFieldNames(7), state.dataIPShortCut->cAlphaArgs(7)));
     464           0 :                 ShowContinueError(state, format("Occurs for {} = {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
     465           0 :                 ErrorsFound = true;
     466             :             }
     467             : 
     468          10 :             highTempRadSys.FracDistribPerson = state.dataIPShortCut->rNumericArgs(9);
     469          10 :             if (highTempRadSys.FracDistribPerson < MinFraction) {
     470           0 :                 highTempRadSys.FracDistribPerson = MinFraction;
     471           0 :                 ShowWarningError(
     472           0 :                     state, format("{} was less than the allowable minimum, reset to minimum value.", state.dataIPShortCut->cNumericFieldNames(9)));
     473           0 :                 ShowContinueError(state, format("Occurs for {} = {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
     474             :             }
     475          10 :             if (highTempRadSys.FracDistribPerson > MaxFraction) {
     476           0 :                 highTempRadSys.FracDistribPerson = MaxFraction;
     477           0 :                 ShowWarningError(
     478           0 :                     state, format("{} was greater than the allowable maximum, reset to maximum value.", state.dataIPShortCut->cNumericFieldNames(9)));
     479           0 :                 ShowContinueError(state, format("Occurs for {} = {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
     480             :             }
     481             : 
     482          10 :             highTempRadSys.TotSurfToDistrib = NumNumbers - 9;
     483             :             //    IF (highTempRadSys%TotSurfToDistrib > MaxDistribSurfaces) THEN
     484             :             //      CALL ShowSevereError(state, 'Trying to distribute radiant energy to too many surfaces for heater
     485             :             //      '//TRIM(state.dataIPShortCut->cAlphaArgs(1))) CALL ShowContinueError(state, 'Occurs for '//TRIM(cCurrentModuleObject)//' =
     486             :             //      '//TRIM(state.dataIPShortCut->cAlphaArgs(1))) ErrorsFound=.TRUE.
     487             :             //    END IF
     488          10 :             highTempRadSys.SurfaceName.allocate(highTempRadSys.TotSurfToDistrib);
     489          10 :             highTempRadSys.SurfacePtr.allocate(highTempRadSys.TotSurfToDistrib);
     490          10 :             highTempRadSys.FracDistribToSurf.allocate(highTempRadSys.TotSurfToDistrib);
     491             : 
     492          10 :             AllFracsSummed = highTempRadSys.FracDistribPerson;
     493          59 :             for (int SurfNum = 1; SurfNum <= highTempRadSys.TotSurfToDistrib; ++SurfNum) {
     494          49 :                 highTempRadSys.SurfaceName(SurfNum) = state.dataIPShortCut->cAlphaArgs(SurfNum + 7);
     495          49 :                 highTempRadSys.SurfacePtr(SurfNum) = HeatBalanceIntRadExchange::GetRadiantSystemSurface(
     496          49 :                     state, cCurrentModuleObject, highTempRadSys.Name, highTempRadSys.ZonePtr, highTempRadSys.SurfaceName(SurfNum), ErrorsFound);
     497          49 :                 highTempRadSys.FracDistribToSurf(SurfNum) = state.dataIPShortCut->rNumericArgs(SurfNum + 9);
     498             :                 // Error trap for fractions that are out of range
     499          49 :                 if (highTempRadSys.FracDistribToSurf(SurfNum) < MinFraction) {
     500           0 :                     highTempRadSys.FracDistribToSurf(SurfNum) = MinFraction;
     501           0 :                     ShowWarningError(state,
     502           0 :                                      format("{} was less than the allowable minimum, reset to minimum value.",
     503           0 :                                             state.dataIPShortCut->cNumericFieldNames(SurfNum + 9)));
     504           0 :                     ShowContinueError(state, format("Occurs for {} = {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
     505             :                 }
     506          49 :                 if (highTempRadSys.FracDistribToSurf(SurfNum) > MaxFraction) {
     507           0 :                     highTempRadSys.FracDistribToSurf(SurfNum) = MaxFraction;
     508           0 :                     ShowWarningError(state,
     509           0 :                                      format("{} was greater than the allowable maximum, reset to maximum value.",
     510           0 :                                             state.dataIPShortCut->cNumericFieldNames(SurfNum + 9)));
     511           0 :                     ShowContinueError(state, format("Occurs for {} = {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
     512             :                 }
     513             : 
     514          49 :                 if (highTempRadSys.SurfacePtr(SurfNum) != 0) {
     515          49 :                     state.dataSurface->surfIntConv(highTempRadSys.SurfacePtr(SurfNum)).getsRadiantHeat = true;
     516          49 :                     state.dataSurface->allGetsRadiantHeatSurfaceList.emplace_back(highTempRadSys.SurfacePtr(SurfNum));
     517             :                 }
     518             : 
     519          49 :                 AllFracsSummed += highTempRadSys.FracDistribToSurf(SurfNum);
     520             : 
     521             :             } // ...end of DO loop through surfaces that the heater radiates to.
     522             : 
     523             :             // Error trap if the fractions add up to greater than 1.0
     524          10 :             if (AllFracsSummed > (MaxFraction + 0.01)) {
     525           0 :                 ShowSevereError(
     526             :                     state,
     527           0 :                     format("Fraction of radiation distributed to surfaces sums up to greater than 1 for {}", state.dataIPShortCut->cAlphaArgs(1)));
     528           0 :                 ShowContinueError(state, format("Occurs for {} = {}", cCurrentModuleObject, state.dataIPShortCut->cAlphaArgs(1)));
     529           0 :                 ErrorsFound = true;
     530             :             }
     531          10 :             if (AllFracsSummed < (MaxFraction - 0.01)) { // User didn't distribute all of the radiation warn that some will be lost
     532           0 :                 Real64 TotalFracToSurfs = AllFracsSummed - highTempRadSys.FracDistribPerson;
     533           0 :                 FracOfRadPotentiallyLost = 1.0 - AllFracsSummed;
     534           0 :                 ShowSevereError(state,
     535           0 :                                 format("Fraction of radiation distributed to surfaces and people sums up to less than 1 for {}",
     536           0 :                                        state.dataIPShortCut->cAlphaArgs(1)));
     537           0 :                 ShowContinueError(state, "This would result in some of the radiant energy delivered by the high temp radiant heater being lost.");
     538           0 :                 ShowContinueError(state, format("The sum of all radiation fractions to surfaces = {:.5T}", TotalFracToSurfs));
     539           0 :                 ShowContinueError(state, format("The radiant fraction to people = {:.5T}", highTempRadSys.FracDistribPerson));
     540           0 :                 ShowContinueError(state, format("So, all radiant fractions including surfaces and people = {:.5T}", AllFracsSummed));
     541           0 :                 ShowContinueError(state,
     542           0 :                                   format("This means that the fraction of radiant energy that would be lost from the high temperature radiant heater "
     543             :                                          "would be = {:.5T}",
     544             :                                          FracOfRadPotentiallyLost));
     545           0 :                 ShowContinueError(state,
     546           0 :                                   format("Please check and correct this so that all radiant energy is accounted for in {} = {}",
     547             :                                          cCurrentModuleObject,
     548           0 :                                          state.dataIPShortCut->cAlphaArgs(1)));
     549           0 :                 ErrorsFound = true;
     550             :             }
     551             : 
     552             :         } // ...end of DO loop through all of the high temperature radiant heaters
     553             : 
     554             :         // Set up the output variables for high temperature radiant heaters
     555             :         // cCurrentModuleObject = "ZoneHVAC:HighTemperatureRadiant"
     556          14 :         for (int Item = 1; Item <= state.dataHighTempRadSys->NumOfHighTempRadSys; ++Item) {
     557          10 :             auto &highTempRadSys = state.dataHighTempRadSys->HighTempRadSys(Item);
     558          20 :             SetupOutputVariable(state,
     559             :                                 "Zone Radiant HVAC Heating Rate",
     560             :                                 Constant::Units::W,
     561          10 :                                 highTempRadSys.HeatPower,
     562             :                                 OutputProcessor::TimeStepType::System,
     563             :                                 OutputProcessor::StoreType::Average,
     564          10 :                                 highTempRadSys.Name);
     565          20 :             SetupOutputVariable(state,
     566             :                                 "Zone Radiant HVAC Heating Energy",
     567             :                                 Constant::Units::J,
     568          10 :                                 highTempRadSys.HeatEnergy,
     569             :                                 OutputProcessor::TimeStepType::System,
     570             :                                 OutputProcessor::StoreType::Sum,
     571          10 :                                 highTempRadSys.Name,
     572             :                                 Constant::eResource::EnergyTransfer,
     573             :                                 OutputProcessor::Group::HVAC,
     574             :                                 OutputProcessor::EndUseCat::HeatingCoils);
     575          10 :             if (highTempRadSys.HeaterType == Constant::eResource::NaturalGas) {
     576          14 :                 SetupOutputVariable(state,
     577             :                                     "Zone Radiant HVAC NaturalGas Rate",
     578             :                                     Constant::Units::W,
     579           7 :                                     highTempRadSys.GasPower,
     580             :                                     OutputProcessor::TimeStepType::System,
     581             :                                     OutputProcessor::StoreType::Average,
     582           7 :                                     highTempRadSys.Name);
     583          14 :                 SetupOutputVariable(state,
     584             :                                     "Zone Radiant HVAC NaturalGas Energy",
     585             :                                     Constant::Units::J,
     586           7 :                                     highTempRadSys.GasEnergy,
     587             :                                     OutputProcessor::TimeStepType::System,
     588             :                                     OutputProcessor::StoreType::Sum,
     589           7 :                                     highTempRadSys.Name,
     590             :                                     Constant::eResource::NaturalGas,
     591             :                                     OutputProcessor::Group::HVAC,
     592             :                                     OutputProcessor::EndUseCat::Heating);
     593           3 :             } else if (highTempRadSys.HeaterType == Constant::eResource::Electricity) {
     594           6 :                 SetupOutputVariable(state,
     595             :                                     "Zone Radiant HVAC Electricity Rate",
     596             :                                     Constant::Units::W,
     597           3 :                                     highTempRadSys.ElecPower,
     598             :                                     OutputProcessor::TimeStepType::System,
     599             :                                     OutputProcessor::StoreType::Average,
     600           3 :                                     highTempRadSys.Name);
     601           6 :                 SetupOutputVariable(state,
     602             :                                     "Zone Radiant HVAC Electricity Energy",
     603             :                                     Constant::Units::J,
     604           3 :                                     highTempRadSys.ElecEnergy,
     605             :                                     OutputProcessor::TimeStepType::System,
     606             :                                     OutputProcessor::StoreType::Sum,
     607           3 :                                     highTempRadSys.Name,
     608             :                                     Constant::eResource::Electricity,
     609             :                                     OutputProcessor::Group::HVAC,
     610             :                                     OutputProcessor::EndUseCat::Heating);
     611             :             }
     612             :         }
     613           4 :     }
     614             : 
     615      129408 :     void InitHighTempRadiantSystem(EnergyPlusData &state,
     616             :                                    bool const FirstHVACIteration, // TRUE if 1st HVAC simulation of system timestep
     617             :                                    int const RadSysNum // Index for the low temperature radiant system under consideration within the derived types
     618             :     )
     619             :     {
     620             : 
     621             :         // SUBROUTINE INFORMATION:
     622             :         //       AUTHOR         Rick Strand
     623             :         //       DATE WRITTEN   February 2001
     624             : 
     625             :         // PURPOSE OF THIS SUBROUTINE:
     626             :         // This subroutine initializes variables relating to high temperature
     627             :         // radiant heating systems.
     628             : 
     629             :         // METHODOLOGY EMPLOYED:
     630             :         // Simply initializes whatever needs initializing.
     631             : 
     632             :         // Using/Aliasing
     633             :         using DataZoneEquipment::CheckZoneEquipmentList;
     634             : 
     635      129408 :         if (state.dataHighTempRadSys->firstTime) {
     636           4 :             state.dataHighTempRadSys->MySizeFlag.dimension(state.dataHighTempRadSys->NumOfHighTempRadSys, true);
     637           4 :             state.dataHighTempRadSys->firstTime = false;
     638             :         }
     639             : 
     640             :         // need to check all units to see if they are on Zone Equipment List or issue warning
     641      129408 :         if (!state.dataHighTempRadSys->ZoneEquipmentListChecked && state.dataZoneEquip->ZoneEquipInputsFilled) {
     642           4 :             state.dataHighTempRadSys->ZoneEquipmentListChecked = true;
     643          14 :             for (auto &thisHTRSys : state.dataHighTempRadSys->HighTempRadSys) {
     644          10 :                 if (CheckZoneEquipmentList(state, "ZoneHVAC:HighTemperatureRadiant", thisHTRSys.Name)) continue;
     645           0 :                 ShowSevereError(state,
     646           0 :                                 format("InitHighTempRadiantSystem: Unit=[ZoneHVAC:HighTemperatureRadiant,{}] is not on any ZoneHVAC:EquipmentList.  "
     647             :                                        "It will not be simulated.",
     648           0 :                                        thisHTRSys.Name));
     649             :             }
     650             :         }
     651             : 
     652      129408 :         if (!state.dataGlobal->SysSizingCalc && state.dataHighTempRadSys->MySizeFlag(RadSysNum)) {
     653             :             // for each radiant systen do the sizing once.
     654          10 :             SizeHighTempRadiantSystem(state, RadSysNum);
     655          10 :             state.dataHighTempRadSys->MySizeFlag(RadSysNum) = false;
     656             :         }
     657             : 
     658      129408 :         if (state.dataGlobal->BeginEnvrnFlag && state.dataHighTempRadSys->MyEnvrnFlag) {
     659          74 :             for (auto &thisHTR : state.dataHighTempRadSys->HighTempRadSys) {
     660          52 :                 thisHTR.ZeroHTRSourceSumHATsurf = 0.0;
     661          52 :                 thisHTR.QHTRRadSource = 0.0;
     662          52 :                 thisHTR.QHTRRadSrcAvg = 0.0;
     663          52 :                 thisHTR.LastQHTRRadSrc = 0.0;
     664          52 :                 thisHTR.LastSysTimeElapsed = 0.0;
     665          52 :                 thisHTR.LastTimeStepSys = 0.0;
     666             :             }
     667          22 :             state.dataHighTempRadSys->MyEnvrnFlag = false;
     668             :         }
     669      129408 :         if (!state.dataGlobal->BeginEnvrnFlag) {
     670      129113 :             state.dataHighTempRadSys->MyEnvrnFlag = true;
     671             :         }
     672             : 
     673      129408 :         if (state.dataGlobal->BeginTimeStepFlag && FirstHVACIteration) { // This is the first pass through in a particular time step
     674       19957 :             auto &thisHTR = state.dataHighTempRadSys->HighTempRadSys(RadSysNum);
     675       19957 :             thisHTR.ZeroHTRSourceSumHATsurf =
     676       19957 :                 state.dataHeatBal->Zone(thisHTR.ZonePtr).sumHATsurf(state); // Set this to figure out what part of the load the radiant system meets
     677       19957 :             thisHTR.QHTRRadSource = 0.0;                                    // Initialize this variable to zero (radiant system defaults to off)
     678       19957 :             thisHTR.QHTRRadSrcAvg = 0.0;                                    // Initialize this variable to zero (radiant system defaults to off)
     679       19957 :             thisHTR.LastQHTRRadSrc = 0.0;     // At the beginning of a time step, reset to zero so average calculation can start again
     680       19957 :             thisHTR.LastSysTimeElapsed = 0.0; // At the beginning of a time step, reset to zero so average calculation can start again
     681       19957 :             thisHTR.LastTimeStepSys = 0.0;    // At the beginning of a time step, reset to zero so average calculation can start again
     682             :         }
     683      129408 :     }
     684             : 
     685          10 :     void SizeHighTempRadiantSystem(EnergyPlusData &state, int const RadSysNum)
     686             :     {
     687             : 
     688             :         // SUBROUTINE INFORMATION:
     689             :         //       AUTHOR         Fred Buhl
     690             :         //       DATE WRITTEN   February 2002
     691             :         //       MODIFIED       August 2013 Daeho Kang, add component sizing table entries
     692             :         //                      July 2014, B. Nigusse, added scalable sizing
     693             : 
     694             :         // PURPOSE OF THIS SUBROUTINE:
     695             :         // This subroutine is for sizing high temperature radiant components for which max power input has not been
     696             :         // specified in the input.
     697             : 
     698             :         // METHODOLOGY EMPLOYED:
     699             :         // Obtains design heating load from the zone sizing arrays
     700             : 
     701             :         // Using/Aliasing
     702          10 :         auto &thisHTR = state.dataHighTempRadSys->HighTempRadSys(RadSysNum);
     703             : 
     704             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS
     705             :         Real64 TempSize; // autosized value of coil input field
     706          10 :         state.dataSize->DataScalableCapSizingON = false;
     707             : 
     708          10 :         int const curZoneEqNum = state.dataSize->CurZoneEqNum;
     709             : 
     710          10 :         if (curZoneEqNum > 0) {
     711          10 :             auto &zoneEqSizing = state.dataSize->ZoneEqSizing(curZoneEqNum);
     712             : 
     713          10 :             state.dataSize->DataFracOfAutosizedHeatingCapacity = 1.0;
     714          10 :             state.dataSize->DataZoneNumber = thisHTR.ZonePtr;
     715             :             // Integer representation of sizing method name (e.g., CoolingAirflowSizing, HeatingCapacitySizing, etc.)
     716          10 :             int SizingMethod = HVAC::HeatingCapacitySizing;
     717          10 :             int FieldNum = 1;
     718          10 :             std::string const SizingString = format("{} [W]", state.dataHighTempRadSys->HighTempRadSysNumericFields(RadSysNum).FieldNames(FieldNum));
     719             :             // capacity sizing methods (HeatingDesignCapacity, CapacityPerFloorArea, FractionOfAutosizedCoolingCapacity, and
     720             :             // FractionOfAutosizedHeatingCapacity )
     721          10 :             int CapSizingMethod = static_cast<int>(thisHTR.HeatingCapMethod);
     722          10 :             zoneEqSizing.SizingMethod(SizingMethod) = CapSizingMethod;
     723          10 :             if (CapSizingMethod == DataSizing::HeatingDesignCapacity || CapSizingMethod == DataSizing::CapacityPerFloorArea ||
     724             :                 CapSizingMethod == DataSizing::FractionOfAutosizedHeatingCapacity) {
     725          10 :                 std::string_view const CompType = "ZoneHVAC:HighTemperatureRadiant";
     726          10 :                 std::string_view const CompName = thisHTR.Name;
     727             : 
     728          10 :                 if (CapSizingMethod == DataSizing::HeatingDesignCapacity) {
     729          10 :                     if (thisHTR.ScaledHeatingCapacity == DataSizing::AutoSize) {
     730           1 :                         CheckZoneSizing(state, CompType, CompName);
     731           1 :                         zoneEqSizing.DesHeatingLoad =
     732           1 :                             state.dataSize->FinalZoneSizing(curZoneEqNum).NonAirSysDesHeatLoad / (thisHTR.FracRadiant + thisHTR.FracConvect);
     733             :                     } else {
     734           9 :                         zoneEqSizing.DesHeatingLoad = thisHTR.ScaledHeatingCapacity;
     735             :                     }
     736          10 :                     zoneEqSizing.HeatingCapacity = true;
     737          10 :                     TempSize = zoneEqSizing.DesHeatingLoad;
     738           0 :                 } else if (CapSizingMethod == DataSizing::CapacityPerFloorArea) {
     739           0 :                     zoneEqSizing.HeatingCapacity = true;
     740           0 :                     zoneEqSizing.DesHeatingLoad = thisHTR.ScaledHeatingCapacity * state.dataHeatBal->Zone(state.dataSize->DataZoneNumber).FloorArea;
     741           0 :                     TempSize = zoneEqSizing.DesHeatingLoad;
     742           0 :                     state.dataSize->DataScalableCapSizingON = true;
     743           0 :                 } else if (CapSizingMethod == DataSizing::FractionOfAutosizedHeatingCapacity) {
     744           0 :                     CheckZoneSizing(state, CompType, CompName);
     745           0 :                     zoneEqSizing.HeatingCapacity = true;
     746           0 :                     state.dataSize->DataFracOfAutosizedHeatingCapacity = thisHTR.ScaledHeatingCapacity;
     747           0 :                     zoneEqSizing.DesHeatingLoad =
     748           0 :                         state.dataSize->FinalZoneSizing(curZoneEqNum).NonAirSysDesHeatLoad / (thisHTR.FracRadiant + thisHTR.FracConvect);
     749           0 :                     TempSize = DataSizing::AutoSize;
     750           0 :                     state.dataSize->DataScalableCapSizingON = true;
     751             :                 } else {
     752           0 :                     TempSize = thisHTR.ScaledHeatingCapacity;
     753             :                 }
     754          10 :                 bool PrintFlag = true;
     755          10 :                 bool errorsFound = false;
     756          10 :                 constexpr std::string_view RoutineName = "SizeHighTempRadiantSystem";
     757          10 :                 HeatingCapacitySizer sizerHeatingCapacity;
     758          10 :                 sizerHeatingCapacity.overrideSizingString(SizingString);
     759          10 :                 sizerHeatingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
     760          10 :                 thisHTR.MaxPowerCapac = sizerHeatingCapacity.size(state, TempSize, errorsFound);
     761          10 :                 state.dataSize->DataScalableCapSizingON = false;
     762          10 :             }
     763          10 :         }
     764          10 :     }
     765             : 
     766       44259 :     void CalcHighTempRadiantSystem(EnergyPlusData &state, int const RadSysNum) // name of the low temperature radiant system
     767             :     {
     768             : 
     769             :         // SUBROUTINE INFORMATION:
     770             :         //       AUTHOR         Rick Strand
     771             :         //       DATE WRITTEN   February 2001
     772             : 
     773             :         // PURPOSE OF THIS SUBROUTINE:
     774             :         // This subroutine does all of the stuff that is necessary to simulate
     775             :         // a high temperature radiant heating system.
     776             : 
     777             :         // METHODOLOGY EMPLOYED:
     778             :         // Follows the methods used by many other pieces of zone equipment except
     779             :         // that we are controlling the input to the heater element.  Note that
     780             :         // cooling is not allowed for such a system.  Controls are very basic at
     781             :         // this point using just a linear interpolation between being off at
     782             :         // one end of the throttling range, fully on at the other end, and varying
     783             :         // linearly in between.
     784             : 
     785             :         // REFERENCES:
     786             :         // Other EnergyPlus modules
     787             :         // Building Systems Laboratory, BLAST User's Guide/Reference.
     788             :         // Fanger, P.O. "Analysis and Applications in Environmental Engineering",
     789             :         //   Danish Technical Press, 1970.
     790             :         // Maloney, Dan. 1987. "Development of a radiant heater model and the
     791             :         //   incorporation of thermal comfort considerations into the BLAST
     792             :         //   energy analysis program", M.S. thesis, University of Illinois at
     793             :         //   Urbana-Champaign (Dept. of Mechanical and Industrial Engineering).
     794             : 
     795             :         // Using/Aliasing
     796       44259 :         auto &thisHTR = state.dataHighTempRadSys->HighTempRadSys(RadSysNum);
     797             : 
     798             :         // initialize local variables
     799       44259 :         int ZoneNum = thisHTR.ZonePtr;
     800       44259 :         Real64 HeatFrac = 0.0; // fraction of maximum energy input to radiant system [dimensionless]
     801             : 
     802       44259 :         if (ScheduleManager::GetCurrentScheduleValue(state, thisHTR.SchedPtr) <= 0) {
     803             : 
     804             :             // Unit is off or has no load upon it; set the flow rates to zero and then
     805             :             // simulate the components with the no flow conditions
     806       22803 :             thisHTR.QHTRRadSource = 0.0;
     807             : 
     808             :         } else { // Unit might be on-->this section is intended to control the output of the
     809             :             // high temperature radiant heater (temperature controlled)
     810             : 
     811             :             // Determine the current setpoint temperature and the temperature at which the unit should be completely off
     812       21456 :             Real64 SetPtTemp = ScheduleManager::GetCurrentScheduleValue(state, thisHTR.SetptSchedPtr);
     813       21456 :             Real64 OffTemp = SetPtTemp + 0.5 * thisHTR.ThrottlRange;
     814       21456 :             auto &thisZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum);
     815       21456 :             Real64 OpTemp = (thisZoneHB.MAT + thisZoneHB.MRT) / 2.0; // Approximate the "operative" temperature
     816             : 
     817             :             // Determine the fraction of maximum power to the unit (limiting the fraction range from zero to unity)
     818       21456 :             switch (thisHTR.ControlType) {
     819        4127 :             case RadControlType::MATControl: {
     820        4127 :                 HeatFrac = (OffTemp - thisZoneHB.MAT) / thisHTR.ThrottlRange;
     821        4127 :             } break;
     822        4127 :             case RadControlType::MRTControl: {
     823        4127 :                 HeatFrac = (OffTemp - thisZoneHB.MRT) / thisHTR.ThrottlRange;
     824        4127 :             } break;
     825       13202 :             case RadControlType::OperativeControl: {
     826       13202 :                 OpTemp = 0.5 * (thisZoneHB.MAT + thisZoneHB.MRT);
     827       13202 :                 HeatFrac = (OffTemp - OpTemp) / thisHTR.ThrottlRange;
     828       13202 :             } break;
     829           0 :             default:
     830           0 :                 break;
     831             :             }
     832       21456 :             if (HeatFrac < 0.0) HeatFrac = 0.0;
     833       21456 :             if (HeatFrac > 1.0) HeatFrac = 1.0;
     834             : 
     835             :             // Set the heat source for the high temperature electric radiant system
     836       21456 :             thisHTR.QHTRRadSource = HeatFrac * thisHTR.MaxPowerCapac;
     837             :         }
     838       44259 :     }
     839             : 
     840       85149 :     void CalcHighTempRadiantSystemSP(
     841             :         EnergyPlusData &state,
     842             :         [[maybe_unused]] bool const FirstHVACIteration, // true if this is the first HVAC iteration at this system time step !unused1208
     843             :         int const RadSysNum                             // name of the low temperature radiant system
     844             :     )
     845             :     {
     846             : 
     847             :         // SUBROUTINE INFORMATION:
     848             :         //       AUTHOR         Rick Strand
     849             :         //       DATE WRITTEN   February 2008
     850             :         //       MODIFIED       Sep 2011 LKL/BG - resimulate only zones needing it for Radiant systems
     851             : 
     852             :         // PURPOSE OF THIS SUBROUTINE:
     853             :         // This subroutine does all of the stuff that is necessary to simulate
     854             :         // a high temperature radiant heating system using setpoint temperature control.
     855             : 
     856             :         // METHODOLOGY EMPLOYED:
     857             :         // Follows the methods used by many other pieces of zone equipment except
     858             :         // that we are controlling the input to the heater element.  Note that
     859             :         // cooling is not allowed for such a system.  Controls are very basic and
     860             :         // use an iterative approach to get close to what we need.
     861             : 
     862             :         // REFERENCES:
     863             :         // Other EnergyPlus modules
     864             :         // Building Systems Laboratory, BLAST User's Guide/Reference.
     865             :         // Fanger, P.O. "Analysis and Applications in Environmental Engineering",
     866             :         //   Danish Technical Press, 1970.
     867             :         // Maloney, Dan. 1987. "Development of a radiant heater model and the
     868             :         //   incorporation of thermal comfort considerations into the BLAST
     869             :         //   energy analysis program", M.S. thesis, University of Illinois at
     870             :         //   Urbana-Champaign (Dept. of Mechanical and Industrial Engineering).
     871             : 
     872             :         // Using/Aliasing
     873       85149 :         auto &thisHTR = state.dataHighTempRadSys->HighTempRadSys(RadSysNum);
     874             : 
     875             :         // SUBROUTINE PARAMETER DEFINITIONS:
     876       85149 :         float const TempConvToler(0.1f); // Temperature controller tries to converge to within 0.1C
     877       85149 :         int constexpr MaxIterations(10); // Maximum number of iterations to achieve temperature control
     878             :         // (10 interval halvings achieves control to 0.1% of capacity)
     879             :         // These two parameters are intended to achieve reasonable control
     880             :         // without excessive run times.
     881             : 
     882             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     883       85149 :         Real64 ZoneTemp(0.0); // zone temperature (MAT, MRT, or Operative Temperature, depending on control type) [C]
     884             : 
     885             :         // initialize local variables
     886       85149 :         int ZoneNum = thisHTR.ZonePtr;
     887       85149 :         thisHTR.QHTRRadSource = 0.0;
     888             : 
     889       85149 :         if (ScheduleManager::GetCurrentScheduleValue(state, thisHTR.SchedPtr) > 0) {
     890             : 
     891             :             // Unit is scheduled on-->this section is intended to control the output of the
     892             :             // high temperature radiant heater (temperature controlled)
     893             : 
     894             :             // Determine the current setpoint temperature and the temperature at which the unit should be completely off
     895       85149 :             Real64 SetPtTemp = ScheduleManager::GetCurrentScheduleValue(state, thisHTR.SetptSchedPtr);
     896             : 
     897             :             // Now, distribute the radiant energy of all systems to the appropriate
     898             :             // surfaces, to people, and the air; determine the latent portion
     899       85149 :             DistributeHTRadGains(state);
     900             : 
     901             :             // Now "simulate" the system by recalculating the heat balances
     902       85149 :             HeatBalanceSurfaceManager::CalcHeatBalanceOutsideSurf(state, ZoneNum);
     903       85149 :             HeatBalanceSurfaceManager::CalcHeatBalanceInsideSurf(state, ZoneNum);
     904             : 
     905             :             // First determine whether or not the unit should be on
     906             :             // Determine the proper temperature on which to control
     907       85149 :             auto &thisZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum);
     908       85149 :             switch (thisHTR.ControlType) {
     909       28383 :             case RadControlType::MATSPControl: {
     910       28383 :                 ZoneTemp = thisZoneHB.MAT;
     911       28383 :             } break;
     912       28383 :             case RadControlType::MRTSPControl: {
     913       28383 :                 ZoneTemp = thisZoneHB.MRT;
     914       28383 :             } break;
     915       28383 :             case RadControlType::OperativeSPControl: {
     916       28383 :                 ZoneTemp = 0.5 * (thisZoneHB.MAT + thisZoneHB.MRT);
     917       28383 :             } break;
     918           0 :             default: {
     919           0 :                 assert(false);
     920             :             } break;
     921             :             }
     922             : 
     923       85149 :             if (ZoneTemp < (SetPtTemp - TempConvToler)) {
     924             : 
     925             :                 // Use simple interval halving to find the best operating fraction to achieve proper temperature control
     926       21920 :                 int IterNum = 0;
     927       21920 :                 bool ConvergFlag = false;
     928             :                 float HeatFrac; // fraction of maximum energy input to radiant system [dimensionless]
     929       21920 :                 float HeatFracMax = 1.0;
     930       21920 :                 float HeatFracMin = 0.0;
     931             : 
     932       43840 :                 while ((IterNum <= MaxIterations) && (!ConvergFlag)) {
     933             : 
     934             :                     // In the first iteration (IterNum=0), try full capacity and see if that is the best solution
     935       21920 :                     if (IterNum == 0) {
     936       21920 :                         HeatFrac = 1.0;
     937             :                     } else {
     938           0 :                         HeatFrac = (HeatFracMin + HeatFracMax) / 2.0;
     939             :                     }
     940             : 
     941             :                     // Set the heat source for the high temperature radiant system
     942       21920 :                     thisHTR.QHTRRadSource = HeatFrac * thisHTR.MaxPowerCapac;
     943             : 
     944             :                     // Now, distribute the radiant energy of all systems to the appropriate
     945             :                     // surfaces, to people, and the air; determine the latent portion
     946       21920 :                     DistributeHTRadGains(state);
     947             : 
     948             :                     // Now "simulate" the system by recalculating the heat balances
     949       21920 :                     HeatBalanceSurfaceManager::CalcHeatBalanceOutsideSurf(state, ZoneNum);
     950       21920 :                     HeatBalanceSurfaceManager::CalcHeatBalanceInsideSurf(state, ZoneNum);
     951             : 
     952             :                     // Redetermine the current value of the controlling temperature
     953       21920 :                     auto &thisZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum);
     954       21920 :                     switch (thisHTR.ControlType) {
     955           0 :                     case RadControlType::MATControl: {
     956           0 :                         ZoneTemp = thisZoneHB.MAT;
     957           0 :                     } break;
     958           0 :                     case RadControlType::MRTControl: {
     959           0 :                         ZoneTemp = thisZoneHB.MRT;
     960           0 :                     } break;
     961           0 :                     case RadControlType::OperativeControl: {
     962           0 :                         ZoneTemp = 0.5 * (thisZoneHB.MAT + thisZoneHB.MRT);
     963           0 :                     } break;
     964       21920 :                     default:
     965       21920 :                         break;
     966             :                     }
     967             : 
     968       21920 :                     if ((std::abs(ZoneTemp - SetPtTemp)) <= TempConvToler) {
     969             :                         // The radiant heater has controlled the zone temperature to the appropriate level--stop iterating
     970           0 :                         ConvergFlag = true;
     971       21920 :                     } else if (ZoneTemp < SetPtTemp) {
     972             :                         // The zone temperature is too low--try increasing the radiant heater output
     973       21920 :                         if (IterNum == 0) {
     974             :                             // Heater already at capacity--this is the best that we can do
     975       21920 :                             ConvergFlag = true;
     976             :                         } else {
     977           0 :                             HeatFracMin = HeatFrac;
     978             :                         }
     979             :                     } else { // (ZoneTemp > SetPtTemp)
     980             :                         // The zone temperature is too high--try decreasing the radiant heater output
     981           0 :                         if (IterNum > 0) HeatFracMax = HeatFrac;
     982             :                     }
     983             : 
     984       21920 :                     ++IterNum;
     985             :                 }
     986             :             }
     987             :         }
     988       85149 :     }
     989             : 
     990      129408 :     void UpdateHighTempRadiantSystem(EnergyPlusData &state,
     991             :                                      int const RadSysNum, // Index for the low temperature radiant system under consideration within the derived types
     992             :                                      Real64 &LoadMet      // load met by the radiant system, in Watts
     993             :     )
     994             :     {
     995             : 
     996             :         // SUBROUTINE INFORMATION:
     997             :         //       AUTHOR         Rick Strand
     998             :         //       DATE WRITTEN   February 2001
     999             : 
    1000             :         // PURPOSE OF THIS SUBROUTINE:
    1001             :         // This subroutine does any updating that needs to be done for high
    1002             :         // temperature radiant heating systems.  This routine has two functions.
    1003             :         // First, it needs to keep track of the average high temperature
    1004             :         // radiant source.  The method for doing this is similar to low
    1005             :         // temperature systems except that heat input is kept locally on
    1006             :         // a system basis rather than a surface basis.  This is because a high
    1007             :         // temperature system affects many surfaces while a low temperature
    1008             :         // system directly affects only one surface.  This leads to the second
    1009             :         // function of this subroutine which is to account for the affect of
    1010             :         // all high temperature radiant systems on each surface.  This
    1011             :         // distribution must be "redone" every time to be sure that we have
    1012             :         // properly accounted for all of the systems.
    1013             : 
    1014             :         // METHODOLOGY EMPLOYED:
    1015             :         // For the source average update, if the system time step elapsed is
    1016             :         // still what it used to be, then either we are still iterating or we
    1017             :         // had to go back and shorten the time step.  As a result, we have to
    1018             :         // subtract out the previous value that we added.  If the system time
    1019             :         // step elapsed is different, then we just need to add the new values
    1020             :         // to the running average.
    1021             : 
    1022             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1023             :         int ZoneNum; // Zone index number for the current radiant system
    1024      129408 :         Real64 SysTimeElapsed = state.dataHVACGlobal->SysTimeElapsed;
    1025      129408 :         Real64 TimeStepSys = state.dataHVACGlobal->TimeStepSys;
    1026      129408 :         auto &thisHTR = state.dataHighTempRadSys->HighTempRadSys(RadSysNum);
    1027             : 
    1028             :         // First, update the running average if necessary...
    1029      129408 :         if (thisHTR.LastSysTimeElapsed == SysTimeElapsed) {
    1030             :             // Still iterating or reducing system time step, so subtract old values which were
    1031             :             // not valid
    1032       91888 :             thisHTR.QHTRRadSrcAvg -= thisHTR.LastQHTRRadSrc * thisHTR.LastTimeStepSys / state.dataGlobal->TimeStepZone;
    1033             :         }
    1034             : 
    1035             :         // Update the running average and the "last" values with the current values of the appropriate variables
    1036      129408 :         thisHTR.QHTRRadSrcAvg += thisHTR.QHTRRadSource * TimeStepSys / state.dataGlobal->TimeStepZone;
    1037             : 
    1038      129408 :         thisHTR.LastQHTRRadSrc = thisHTR.QHTRRadSource;
    1039      129408 :         thisHTR.LastSysTimeElapsed = SysTimeElapsed;
    1040      129408 :         thisHTR.LastTimeStepSys = TimeStepSys;
    1041             : 
    1042      129408 :         switch (thisHTR.ControlType) {
    1043       44259 :         case RadControlType::MATControl:
    1044             :         case RadControlType::MRTControl:
    1045             :         case RadControlType::OperativeControl: {
    1046             :             // Only need to do this for the non-SP controls (SP has already done this enough)
    1047             :             // Now, distribute the radiant energy of all systems to the appropriate
    1048             :             // surfaces, to people, and the air; determine the latent portion
    1049       44259 :             DistributeHTRadGains(state);
    1050             : 
    1051             :             // Now "simulate" the system by recalculating the heat balances
    1052       44259 :             ZoneNum = thisHTR.ZonePtr;
    1053       44259 :             HeatBalanceSurfaceManager::CalcHeatBalanceOutsideSurf(state, ZoneNum);
    1054       44259 :             HeatBalanceSurfaceManager::CalcHeatBalanceInsideSurf(state, ZoneNum);
    1055       44259 :         } break;
    1056       85149 :         default:
    1057       85149 :             break;
    1058             :         }
    1059             : 
    1060      129408 :         if (thisHTR.QHTRRadSource <= 0.0) {
    1061       90127 :             LoadMet = 0.0; // System wasn't running so it can't meet a load
    1062             :         } else {
    1063       39281 :             ZoneNum = thisHTR.ZonePtr;
    1064       39281 :             LoadMet = (state.dataHeatBal->Zone(ZoneNum).sumHATsurf(state) - thisHTR.ZeroHTRSourceSumHATsurf) +
    1065       39281 :                       state.dataHeatBalFanSys->SumConvHTRadSys(ZoneNum);
    1066             :         }
    1067      129408 :     }
    1068             : 
    1069     2804482 :     void UpdateHTRadSourceValAvg(EnergyPlusData &state, bool &HighTempRadSysOn) // .TRUE. if the radiant system has run this zone time step
    1070             :     {
    1071             : 
    1072             :         // SUBROUTINE INFORMATION:
    1073             :         //       AUTHOR         Rick Strand
    1074             :         //       DATE WRITTEN   February 2001
    1075             : 
    1076             :         // PURPOSE OF THIS SUBROUTINE:
    1077             :         // To transfer the average value of the heat source over the entire
    1078             :         // zone time step back to the heat balance routines so that the heat
    1079             :         // balance algorithms can simulate one last time with the average source
    1080             :         // to maintain some reasonable amount of continuity and energy balance
    1081             :         // in the temperature and flux histories.
    1082             : 
    1083             :         // METHODOLOGY EMPLOYED:
    1084             :         // All of the record keeping for the average term is done in the Update
    1085             :         // routine so the only other thing that this subroutine does is check to
    1086             :         // see if the system was even on.  If any average term is non-zero, then
    1087             :         // one or more of the radiant systems was running.
    1088             : 
    1089     2804482 :         HighTempRadSysOn = false;
    1090             : 
    1091             :         // If this was never allocated, then there are no radiant systems in this input file (just RETURN)
    1092     2804482 :         if (state.dataHighTempRadSys->NumOfHighTempRadSys == 0) return;
    1093             : 
    1094             :         // If it was allocated, then we have to check to see if this was running at all...
    1095       27786 :         for (auto &thisHTR : state.dataHighTempRadSys->HighTempRadSys) {
    1096       19968 :             thisHTR.QHTRRadSource = thisHTR.QHTRRadSrcAvg;
    1097       19968 :             if (thisHTR.QHTRRadSrcAvg != 0.0) HighTempRadSysOn = true;
    1098             :         }
    1099             : 
    1100        7818 :         DistributeHTRadGains(
    1101             :             state); // state.dataHighTempRadSys->HighTempRadSys(RadSysNum).QHTRRadSource has been modified so we need to redistribute gains
    1102             :     }
    1103             : 
    1104      159146 :     void DistributeHTRadGains(EnergyPlusData &state)
    1105             :     {
    1106             : 
    1107             :         // SUBROUTINE INFORMATION:
    1108             :         //       AUTHOR         Rick Strand
    1109             :         //       DATE WRITTEN   February 2001
    1110             :         //       MODIFIED       April 2010 Brent Griffith, max limit to protect surface temperature calcs
    1111             : 
    1112             :         // PURPOSE OF THIS SUBROUTINE:
    1113             :         // To distribute the gains from the high temperature radiant heater
    1114             :         // as specified in the user input file.  This includes distribution
    1115             :         // of long wavelength radiant gains to surfaces and "people" as well
    1116             :         // as latent, lost, and convective portions of the total gain.
    1117             : 
    1118             :         // METHODOLOGY EMPLOYED:
    1119             :         // We must cycle through all of the radiant systems because each
    1120             :         // surface could feel the effect of more than one radiant system.
    1121             :         // Note that the energy radiated to people is assumed to affect them
    1122             :         // but them it is assumed to be convected to the air.  This is why
    1123             :         // the convective portion shown below has two parts to it.
    1124             : 
    1125             :         // SUBROUTINE PARAMETER DEFINITIONS:
    1126      159146 :         Real64 constexpr SmallestArea = 0.001; // Smallest area in meters squared (to avoid a divide by zero)
    1127             : 
    1128             :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1129             :         Real64 ThisSurfIntensity; // temporary for W/m2 term for rad on a surface
    1130             : 
    1131             :         // Using/Aliasing
    1132      159146 :         auto &dataHBFS = state.dataHeatBalFanSys;
    1133             : 
    1134             :         // Initialize arrays
    1135      159146 :         dataHBFS->SumConvHTRadSys = 0.0;
    1136      159146 :         dataHBFS->SumLatentHTRadSys = 0.0;
    1137      626108 :         for (auto &thisHTR : state.dataHighTempRadSys->HighTempRadSys) {
    1138     2796534 :             for (int radSurfNum = 1; radSurfNum <= thisHTR.TotSurfToDistrib; ++radSurfNum) {
    1139     2329572 :                 int surfNum = thisHTR.SurfacePtr(radSurfNum);
    1140     2329572 :                 state.dataHeatBalFanSys->surfQRadFromHVAC(surfNum).HTRadSys = 0.0;
    1141             :             }
    1142             :         }
    1143      159146 :         dataHBFS->ZoneQHTRadSysToPerson = 0.0;
    1144             : 
    1145      626108 :         for (auto &thisHTR : state.dataHighTempRadSys->HighTempRadSys) {
    1146      466962 :             int ZoneNum = thisHTR.ZonePtr;
    1147             : 
    1148      466962 :             dataHBFS->ZoneQHTRadSysToPerson(ZoneNum) = thisHTR.QHTRRadSource * thisHTR.FracRadiant * thisHTR.FracDistribPerson;
    1149      466962 :             dataHBFS->SumConvHTRadSys(ZoneNum) += thisHTR.QHTRRadSource * thisHTR.FracConvect;
    1150      466962 :             dataHBFS->SumLatentHTRadSys(ZoneNum) += thisHTR.QHTRRadSource * thisHTR.FracLatent;
    1151             : 
    1152     2796534 :             for (int RadSurfNum = 1; RadSurfNum <= thisHTR.TotSurfToDistrib; ++RadSurfNum) {
    1153     2329572 :                 int SurfNum = thisHTR.SurfacePtr(RadSurfNum);
    1154     2329572 :                 if (state.dataSurface->Surface(SurfNum).Area > SmallestArea) {
    1155     2329572 :                     ThisSurfIntensity = (thisHTR.QHTRRadSource * thisHTR.FracRadiant * thisHTR.FracDistribToSurf(RadSurfNum) /
    1156     2329572 :                                          state.dataSurface->Surface(SurfNum).Area);
    1157     2329572 :                     state.dataHeatBalFanSys->surfQRadFromHVAC(SurfNum).HTRadSys += ThisSurfIntensity;
    1158             : 
    1159     2329572 :                     if (ThisSurfIntensity > DataHeatBalFanSys::MaxRadHeatFlux) { // CR 8074, trap excessive intensity (throws off surface balance )
    1160           0 :                         ShowSevereError(state, "DistributeHTRadGains:  excessive thermal radiation heat flux intensity detected");
    1161           0 :                         ShowContinueError(state, format("Surface = {}", state.dataSurface->Surface(SurfNum).Name));
    1162           0 :                         ShowContinueError(state, format("Surface area = {:.3R} [m2]", state.dataSurface->Surface(SurfNum).Area));
    1163           0 :                         ShowContinueError(state, format("Occurs in ZoneHVAC:HighTemperatureRadiant = {}", thisHTR.Name));
    1164           0 :                         ShowContinueError(state, format("Radiation intensity = {:.2R} [W/m2]", ThisSurfIntensity));
    1165           0 :                         ShowContinueError(state, "Assign a larger surface area or more surfaces in ZoneHVAC:HighTemperatureRadiant");
    1166           0 :                         ShowFatalError(state, "DistributeHTRadGains:  excessive thermal radiation heat flux intensity detected");
    1167             :                     }
    1168             :                 } else { // small surface
    1169           0 :                     ShowSevereError(state, "DistributeHTRadGains:  surface not large enough to receive thermal radiation heat flux");
    1170           0 :                     ShowContinueError(state, format("Surface = {}", state.dataSurface->Surface(SurfNum).Name));
    1171           0 :                     ShowContinueError(state, format("Surface area = {:.3R} [m2]", state.dataSurface->Surface(SurfNum).Area));
    1172           0 :                     ShowContinueError(state, format("Occurs in ZoneHVAC:HighTemperatureRadiant = {}", thisHTR.Name));
    1173           0 :                     ShowContinueError(state, "Assign a larger surface area or more surfaces in ZoneHVAC:HighTemperatureRadiant");
    1174           0 :                     ShowFatalError(state, "DistributeHTRadGains:  surface not large enough to receive thermal radiation heat flux");
    1175             :                 }
    1176             :             }
    1177             :         }
    1178             : 
    1179             :         // Here an assumption is made regarding radiant heat transfer to people.
    1180             :         // While the ZoneQHTRadSysToPerson array will be used by the thermal comfort
    1181             :         // routines, the energy transfer to people would get lost from the perspective
    1182             :         // of the heat balance.  So, to avoid this net loss of energy which clearly
    1183             :         // gets added to the zones, we must account for it somehow.  This assumption
    1184             :         // that all energy radiated to people is converted to convective energy is
    1185             :         // not very precise, but at least it conserves energy.
    1186      636584 :         for (int ZoneNum = 1; ZoneNum <= state.dataGlobal->NumOfZones; ++ZoneNum) {
    1187      477438 :             dataHBFS->SumConvHTRadSys(ZoneNum) += dataHBFS->ZoneQHTRadSysToPerson(ZoneNum);
    1188             :         }
    1189      159146 :     }
    1190             : 
    1191      129408 :     void ReportHighTempRadiantSystem(EnergyPlusData &state,
    1192             :                                      int const RadSysNum) // Index for the low temperature radiant system under consideration within the derived types
    1193             :     {
    1194             : 
    1195             :         // SUBROUTINE INFORMATION:
    1196             :         //       AUTHOR         Rick Strand
    1197             :         //       DATE WRITTEN   February 2001
    1198             : 
    1199             :         // PURPOSE OF THIS SUBROUTINE:
    1200             :         // This subroutine simply produces output for the high temperature radiant system.
    1201             : 
    1202             :         // Using/Aliasing
    1203      129408 :         Real64 TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
    1204      129408 :         auto &thisHTR = state.dataHighTempRadSys->HighTempRadSys(RadSysNum);
    1205             : 
    1206      129408 :         if (thisHTR.HeaterType == Constant::eResource::NaturalGas) {
    1207      107373 :             thisHTR.GasPower = thisHTR.QHTRRadSource / thisHTR.CombustionEffic;
    1208      107373 :             thisHTR.GasEnergy = thisHTR.GasPower * TimeStepSysSec;
    1209      107373 :             thisHTR.ElecPower = 0.0;
    1210      107373 :             thisHTR.ElecEnergy = 0.0;
    1211       22035 :         } else if (thisHTR.HeaterType == Constant::eResource::Electricity) {
    1212       22035 :             thisHTR.GasPower = 0.0;
    1213       22035 :             thisHTR.GasEnergy = 0.0;
    1214       22035 :             thisHTR.ElecPower = thisHTR.QHTRRadSource;
    1215       22035 :             thisHTR.ElecEnergy = thisHTR.ElecPower * TimeStepSysSec;
    1216             :         } else {
    1217           0 :             ShowWarningError(state, "Someone forgot to add a high temperature radiant heater type to the reporting subroutine");
    1218             :         }
    1219      129408 :         thisHTR.HeatPower = thisHTR.QHTRRadSource;
    1220      129408 :         thisHTR.HeatEnergy = thisHTR.HeatPower * TimeStepSysSec;
    1221      129408 :     }
    1222             : 
    1223             : } // namespace HighTempRadiantSystem
    1224             : 
    1225             : } // namespace EnergyPlus

Generated by: LCOV version 1.14