LCOV - code coverage report
Current view: top level - EnergyPlus - LowTempRadiantSystem.cc (source / functions) Coverage Total Hit
Test: lcov.output.filtered Lines: 42.5 % 2990 1272
Test Date: 2025-05-22 16:09:37 Functions: 58.6 % 29 17

            Line data    Source code
       1              : // EnergyPlus, Copyright (c) 1996-2025, The Board of Trustees of the University of Illinois,
       2              : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
       3              : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
       4              : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
       5              : // contributors. All rights reserved.
       6              : //
       7              : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
       8              : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
       9              : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
      10              : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
      11              : // derivative works, and perform publicly and display publicly, and to permit others to do so.
      12              : //
      13              : // Redistribution and use in source and binary forms, with or without modification, are permitted
      14              : // provided that the following conditions are met:
      15              : //
      16              : // (1) Redistributions of source code must retain the above copyright notice, this list of
      17              : //     conditions and the following disclaimer.
      18              : //
      19              : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
      20              : //     conditions and the following disclaimer in the documentation and/or other materials
      21              : //     provided with the distribution.
      22              : //
      23              : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
      24              : //     the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
      25              : //     used to endorse or promote products derived from this software without specific prior
      26              : //     written permission.
      27              : //
      28              : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
      29              : //     without changes from the version obtained under this License, or (ii) Licensee makes a
      30              : //     reference solely to the software portion of its product, Licensee must refer to the
      31              : //     software as "EnergyPlus version X" software, where "X" is the version number Licensee
      32              : //     obtained under this License and may not use a different name for the software. Except as
      33              : //     specifically required in this Section (4), Licensee shall not use in a company name, a
      34              : //     product name, in advertising, publicity, or other promotional activities any name, trade
      35              : //     name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
      36              : //     similar designation, without the U.S. Department of Energy's prior written consent.
      37              : //
      38              : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
      39              : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
      40              : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
      41              : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      42              : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
      43              : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      44              : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
      45              : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      46              : // POSSIBILITY OF SUCH DAMAGE.
      47              : 
      48              : // C++ Headers
      49              : #include <cassert>
      50              : #include <cmath>
      51              : 
      52              : // ObjexxFCL Headers
      53              : #include <ObjexxFCL/Array.functions.hh>
      54              : #include <ObjexxFCL/Fmath.hh>
      55              : 
      56              : // EnergyPlus Headers
      57              : #include <EnergyPlus/Autosizing/CoolingCapacitySizing.hh>
      58              : #include <EnergyPlus/Autosizing/HeatingCapacitySizing.hh>
      59              : #include <EnergyPlus/BranchNodeConnections.hh>
      60              : #include <EnergyPlus/Construction.hh>
      61              : #include <EnergyPlus/Data/EnergyPlusData.hh>
      62              : #include <EnergyPlus/DataBranchAirLoopPlant.hh>
      63              : #include <EnergyPlus/DataEnvironment.hh>
      64              : #include <EnergyPlus/DataHVACGlobals.hh>
      65              : #include <EnergyPlus/DataHeatBalFanSys.hh>
      66              : #include <EnergyPlus/DataHeatBalSurface.hh>
      67              : #include <EnergyPlus/DataHeatBalance.hh>
      68              : #include <EnergyPlus/DataLoopNode.hh>
      69              : #include <EnergyPlus/DataSizing.hh>
      70              : #include <EnergyPlus/DataSurfaceLists.hh>
      71              : #include <EnergyPlus/DataSurfaces.hh>
      72              : #include <EnergyPlus/DataZoneEquipment.hh>
      73              : #include <EnergyPlus/EMSManager.hh>
      74              : #include <EnergyPlus/FluidProperties.hh>
      75              : #include <EnergyPlus/General.hh>
      76              : #include <EnergyPlus/GeneralRoutines.hh>
      77              : #include <EnergyPlus/GlobalNames.hh>
      78              : #include <EnergyPlus/HeatBalanceSurfaceManager.hh>
      79              : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      80              : #include <EnergyPlus/LowTempRadiantSystem.hh>
      81              : #include <EnergyPlus/NodeInputManager.hh>
      82              : #include <EnergyPlus/OutputProcessor.hh>
      83              : #include <EnergyPlus/Plant/Enums.hh>
      84              : #include <EnergyPlus/PlantUtilities.hh>
      85              : #include <EnergyPlus/Psychrometrics.hh>
      86              : #include <EnergyPlus/ScheduleManager.hh>
      87              : #include <EnergyPlus/UtilityRoutines.hh>
      88              : #include <EnergyPlus/WeatherManager.hh>
      89              : #include <EnergyPlus/ZoneTempPredictorCorrector.hh>
      90              : 
      91              : namespace EnergyPlus {
      92              : 
      93              : namespace LowTempRadiantSystem {
      94              : 
      95              :     // Module containing the routines dealing with the low temperature radiant systems
      96              : 
      97              :     // MODULE INFORMATION:
      98              :     //       AUTHOR         Rick Strand
      99              :     //       DATE WRITTEN   November 2000
     100              :     //       MODIFIED       Rick Strand March 2001 (additional controls, etc.)
     101              :     //                      Rick Strand July 2003 (added constant flow hydronic system)
     102              :     //                      B. Griffith Sept 2010, plant upgrades, generalize fluid properties
     103              :     //                      Rick Strand August 2011 (improved condensation handling)
     104              : 
     105              :     // PURPOSE OF THIS MODULE:
     106              :     // The purpose of this module is to simulate low temperature radiant systems.
     107              :     // It is the intention of this module to cover all types of low temperature
     108              :     // radiant systems: wall, ceiling, floor, heating, cooling, panels, etc.
     109              : 
     110              :     // METHODOLOGY EMPLOYED:
     111              :     // Based on work done in IBLAST, this model has been revised for the structure
     112              :     // of EnergyPlus.  It is still based on the QTF formulation of heat transfer
     113              :     // through building elements with embedded heat sources/sinks.  Note that due
     114              :     // to the fact that a radiant system is both a building heat transfer element
     115              :     // and a controllable system that some iteration between the system and the
     116              :     // surface heat balance routine is necessary.
     117              :     // REFERENCES:
     118              :     // IBLAST-QTF research program, completed in January 1995 (unreleased)
     119              :     // Strand, R.K. 1995. "Heat Source Transfer Functions and Their Application to
     120              :     //   Low Temperature Radiant Heating Systems", Ph.D. dissertation, University
     121              :     //   of Illinois at Urbana-Champaign, Department of Mechanical and Industrial
     122              :     //   Engineering.
     123              :     // Seem, J.E. 1986. "Heat Transfer in Buildings", Ph.D. dissertation, University
     124              :     //   of Wisconsin-Madison.
     125              : 
     126              :     // OTHER NOTES: This module contains three different types of radiant system
     127              :     // models: (a) variable flow hydronic heating/cooling radiant system;
     128              :     // (b) constant flow, variable controlled temperature heating/cooling radiant
     129              :     // system; (c) electric resistance heating radiant system.  Systems (a) and
     130              :     // (b) are hydronic systems--one which varies hydronic flow as the key control
     131              :     // parameter (a) and one which varies the inlet hydronic temperature while
     132              :     // keeping the flow rate through the radiant system constant (b).  In system
     133              :     // (b), the injection rate from the main water loop is varied to obtain the
     134              :     // proper inlet temperature.
     135              : 
     136              :     // USE STATEMENTS:
     137              :     // Use statements for data only modules
     138              :     // Using/Aliasing
     139              :     using HVAC::SmallLoad;
     140              :     using Psychrometrics::PsyTdpFnWPb;
     141              : 
     142              :     // Data
     143              :     // MODULE PARAMETER DEFINITIONS:
     144              :     // System types:
     145              :     constexpr std::string_view cHydronicSystem("ZoneHVAC:LowTemperatureRadiant:VariableFlow");
     146              :     constexpr std::string_view cConstantFlowSystem("ZoneHVAC:LowTemperatureRadiant:ConstantFlow");
     147              : 
     148              :     // DERIVED TYPE DEFINITIONS:
     149              : 
     150              :     // MODULE VARIABLE DECLARATIONS:
     151              :     // Standard, run-of-the-mill variables...
     152              : 
     153              :     // Object Data
     154              :     constexpr std::array<std::string_view, (int)CtrlType::Num> ctrlTypeNames = {"MeanAirTemperature",
     155              :                                                                                 "MeanRadiantTemperature",
     156              :                                                                                 "OperativeTemperature",
     157              :                                                                                 "OutdoorDryBulbTemperature",
     158              :                                                                                 "OutdoorWetBulbTemperature",
     159              :                                                                                 "SurfaceFaceTemperature",
     160              :                                                                                 "SurfaceInteriorTemperature",
     161              :                                                                                 "RunningMeanOutdoorDryBulbTemperature"};
     162              :     constexpr std::array<std::string_view, (int)CtrlType::Num> ctrlTypeNamesUC = {"MEANAIRTEMPERATURE",
     163              :                                                                                   "MEANRADIANTTEMPERATURE",
     164              :                                                                                   "OPERATIVETEMPERATURE",
     165              :                                                                                   "OUTDOORDRYBULBTEMPERATURE",
     166              :                                                                                   "OUTDOORWETBULBTEMPERATURE",
     167              :                                                                                   "SURFACEFACETEMPERATURE",
     168              :                                                                                   "SURFACEINTERIORTEMPERATURE",
     169              :                                                                                   "RUNNINGMEANOUTDOORDRYBULBTEMPERATURE"};
     170              : 
     171              :     constexpr std::array<std::string_view, (int)SetpointType::Num> setpointTypeNames = {"HalfFlowPower", "ZeroFlowPower"};
     172              :     constexpr std::array<std::string_view, (int)SetpointType::Num> setpointTypeNamesUC = {"HALFFLOWPOWER", "ZEROFLOWPOWER"};
     173              : 
     174              :     constexpr std::array<std::string_view, (int)FluidToSlabHeatTransferType::Num> fluidToSlabHeatTransferTypeNames = {"ConvectionOnly",
     175              :                                                                                                                       "ISOStandard"};
     176              :     constexpr std::array<std::string_view, (int)FluidToSlabHeatTransferType::Num> fluidToSlabHeatTransferTypeNamesUC = {"CONVECTIONONLY",
     177              :                                                                                                                         "ISOSTANDARD"};
     178              : 
     179              :     constexpr std::array<std::string_view, (int)CondCtrlType::Num> condCtrlTypeNamesUC = {"OFF", "SIMPLEOFF", "VARIABLEOFF"};
     180              : 
     181              :     constexpr std::array<std::string_view, (int)CircuitCalc::Num> circuitCalcNames = {"OnePerSurface", "CalculateFromCircuitLength"};
     182              :     constexpr std::array<std::string_view, (int)CircuitCalc::Num> circuitCalcNamesUC = {"ONEPERSURFACE", "CALCULATEFROMCIRCUITLENGTH"};
     183              : 
     184            0 :     void SimLowTempRadiantSystem(EnergyPlusData &state,
     185              :                                  std::string_view CompName,     // name of the low temperature radiant system
     186              :                                  bool const FirstHVACIteration, // TRUE if 1st HVAC simulation of system timestep
     187              :                                  Real64 &LoadMet,               // load met by the radiant system, in Watts
     188              :                                  int &CompIndex)
     189              :     {
     190              : 
     191              :         // SUBROUTINE INFORMATION:
     192              :         //       AUTHOR         Rick Strand
     193              :         //       DATE WRITTEN   November 2000
     194              : 
     195              :         // Using/Aliasing
     196              : 
     197              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     198              :         int RadSysNum;         // Radiant system number/index in local derived types
     199              :         SystemType systemType; // Type of radiant system: hydronic, constant flow, or electric
     200            0 :         bool InitErrorFound(false);
     201              : 
     202            0 :         if (state.dataLowTempRadSys->GetInputFlag) {
     203            0 :             GetLowTempRadiantSystem(state);
     204            0 :             state.dataLowTempRadSys->GetInputFlag = false;
     205              :         }
     206              : 
     207              :         // Find the correct Low Temp Radiant System
     208            0 :         if (CompIndex == 0) {
     209            0 :             RadSysNum = Util::FindItemInList(CompName, state.dataLowTempRadSys->RadSysTypes);
     210            0 :             if (RadSysNum == 0) {
     211            0 :                 ShowFatalError(state, format("SimLowTempRadiantSystem: Unit not found={}", CompName));
     212              :             }
     213            0 :             CompIndex = RadSysNum;
     214            0 :             systemType = state.dataLowTempRadSys->RadSysTypes(RadSysNum).systemType;
     215            0 :             switch (systemType) {
     216            0 :             case SystemType::Hydronic: {
     217            0 :                 state.dataLowTempRadSys->RadSysTypes(RadSysNum).CompIndex = Util::FindItemInList(CompName, state.dataLowTempRadSys->HydrRadSys);
     218            0 :             } break;
     219            0 :             case SystemType::ConstantFlow: {
     220            0 :                 state.dataLowTempRadSys->RadSysTypes(RadSysNum).CompIndex = Util::FindItemInList(CompName, state.dataLowTempRadSys->CFloRadSys);
     221            0 :             } break;
     222            0 :             case SystemType::Electric: {
     223            0 :                 state.dataLowTempRadSys->RadSysTypes(RadSysNum).CompIndex = Util::FindItemInList(CompName, state.dataLowTempRadSys->ElecRadSys);
     224            0 :             } break;
     225            0 :             default:
     226            0 :                 break;
     227              :             }
     228              :         } else {
     229            0 :             RadSysNum = CompIndex;
     230            0 :             systemType = state.dataLowTempRadSys->RadSysTypes(RadSysNum).systemType;
     231            0 :             if (RadSysNum > state.dataLowTempRadSys->TotalNumOfRadSystems || RadSysNum < 1) {
     232            0 :                 ShowFatalError(state,
     233            0 :                                format("SimLowTempRadiantSystem:  Invalid CompIndex passed={}, Number of Units={}, Entered Unit name={}",
     234              :                                       RadSysNum,
     235            0 :                                       state.dataLowTempRadSys->TotalNumOfRadSystems,
     236              :                                       CompName));
     237              :             }
     238            0 :             if (state.dataLowTempRadSys->CheckEquipName(RadSysNum)) {
     239            0 :                 if (CompName != state.dataLowTempRadSys->RadSysTypes(RadSysNum).Name) {
     240            0 :                     ShowFatalError(state,
     241            0 :                                    format("SimLowTempRadiantSystem: Invalid CompIndex passed={}, Unit name={}, stored Unit Name for that index={}",
     242              :                                           RadSysNum,
     243              :                                           CompName,
     244            0 :                                           state.dataLowTempRadSys->RadSysTypes(RadSysNum).Name));
     245              :                 }
     246            0 :                 state.dataLowTempRadSys->CheckEquipName(RadSysNum) = false;
     247              :             }
     248              :         }
     249              : 
     250            0 :         InitLowTempRadiantSystem(state, FirstHVACIteration, state.dataLowTempRadSys->RadSysTypes(RadSysNum).CompIndex, systemType, InitErrorFound);
     251            0 :         if (InitErrorFound) {
     252            0 :             ShowFatalError(state,
     253              :                            "InitLowTempRadiantSystem: Preceding error is not allowed to proceed with the simulation.  Correct this input problem.");
     254              :         }
     255              : 
     256              :         // Simulate, update, and report based on the type of radiant system
     257              :         {
     258              :             RadiantSystemBaseData *baseSystem;
     259            0 :             if (systemType == SystemType::Hydronic) {
     260            0 :                 baseSystem = &state.dataLowTempRadSys->HydrRadSys(state.dataLowTempRadSys->RadSysTypes(RadSysNum).CompIndex);
     261            0 :             } else if (systemType == SystemType::ConstantFlow) {
     262            0 :                 baseSystem = &state.dataLowTempRadSys->CFloRadSys(state.dataLowTempRadSys->RadSysTypes(RadSysNum).CompIndex);
     263            0 :             } else if (systemType == SystemType::Electric) {
     264            0 :                 baseSystem = &state.dataLowTempRadSys->ElecRadSys(state.dataLowTempRadSys->RadSysTypes(RadSysNum).CompIndex);
     265              :             } else {
     266            0 :                 ShowFatalError(state, format("SimLowTempRadiantSystem: Illegal system type for system {}", CompName));
     267              :             }
     268              : 
     269            0 :             if ((systemType == SystemType::Hydronic) || (systemType == SystemType::ConstantFlow) || (systemType == SystemType::Electric)) {
     270            0 :                 baseSystem->calculateLowTemperatureRadiantSystem(state, LoadMet);
     271            0 :                 baseSystem->updateLowTemperatureRadiantSystemSurfaces(state);
     272            0 :                 baseSystem->updateLowTemperatureRadiantSystem(state); // Nothing to update for electric systems
     273            0 :                 baseSystem->reportLowTemperatureRadiantSystem(state);
     274              :             }
     275              :         }
     276            0 :     }
     277              : 
     278            5 :     void GetLowTempRadiantSystem(EnergyPlusData &state)
     279              :     {
     280              : 
     281              :         // SUBROUTINE INFORMATION:
     282              :         //       AUTHOR         Rick Strand
     283              :         //       DATE WRITTEN   November 2000
     284              :         //       MODIFIED       August 2003 (added constant flow system, made input extensible)
     285              : 
     286              :         // PURPOSE OF THIS SUBROUTINE:
     287              :         // This subroutine reads the input for low temperature radiant systems
     288              :         // from the user input file.  This will contain all of the information
     289              :         // needed to simulate a low temperature radiant system.
     290              : 
     291              :         // Using/Aliasing
     292              :         using BranchNodeConnections::TestCompSet;
     293              :         using DataSizing::AutoSize;
     294              :         using DataSizing::CapacityPerFloorArea;
     295              :         using DataSizing::CoolingDesignCapacity;
     296              :         using DataSizing::FractionOfAutosizedCoolingCapacity;
     297              :         using DataSizing::FractionOfAutosizedHeatingCapacity;
     298              :         using DataSizing::HeatingDesignCapacity;
     299              : 
     300              :         using NodeInputManager::GetOnlySingleNode;
     301              :         using namespace DataLoopNode;
     302              :         using namespace DataSurfaceLists;
     303              : 
     304              :         // SUBROUTINE PARAMETER DEFINITIONS:
     305            5 :         constexpr std::string_view RoutineName("GetLowTempRadiantSystem: "); // include trailing blank space
     306            5 :         constexpr std::string_view routineName = "GetLowTempRadiantSystem";
     307              : 
     308            5 :         int constexpr iHeatCAPMAlphaNum(5);             // get input index to Low Temperature Radiant system heating capacity sizing method
     309            5 :         int constexpr iHeatDesignCapacityNumericNum(1); // get input index to Low Temperature Radiant system electric heating capacity
     310            5 :         int constexpr iHeatCapacityPerFloorAreaNumericNum(
     311              :             2); // get input index to Low Temperature Radiant system electric heating capacity per floor area sizing
     312            5 :         int constexpr iHeatFracOfAutosizedCapacityNumericNum(
     313              :             3); //  get input index to Low Temperature Radiant system electric heating capacity sizing as fraction of autosized heating capacity
     314              : 
     315              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     316            5 :         std::string CurrentModuleObject;       // for ease in getting objects
     317            5 :         Array1D_string Alphas;                 // Alpha items for object
     318            5 :         Array1D_string cAlphaFields;           // Alpha field names
     319            5 :         Array1D_string cNumericFields;         // Numeric field names
     320            5 :         Array1D_bool AssignedAsRadiantSurface; // Set to true when a surface is part of a radiant system
     321              :         int CheckSurfNum;                      // Surface number to check to see if it has already been used by a radiant system
     322            5 :         bool ErrorsFound(false);               // Set to true if errors in input, fatal at end of routine
     323              :         int IOStatus;                          // Used in GetObjectItem
     324              :         int Item;                              // Item to be "gotten"
     325              :         int MaxAlphas;                         // Maximum number of alphas for these input keywords
     326              :         int MaxNumbers;                        // Maximum number of numbers for these input keywords
     327            5 :         Array1D<Real64> Numbers;               // Numeric items for object
     328              :         int NumAlphas;                         // Number of Alphas for each GetObjectItem call
     329              :         int NumArgs;                           // Unused variable that is part of a subroutine call
     330              :         int NumNumbers;                        // Number of Numbers for each GetObjectItem call
     331              :         int SurfListNum;                       // Index within the SurfList derived type for a surface list name
     332              :         int SurfNum;                           // DO loop counter for surfaces
     333              :         int BaseNum;                           // Temporary number for creating RadiantSystemTypes structure
     334            5 :         Array1D_bool lAlphaBlanks;             // Logical array, alpha field input BLANK = .TRUE.
     335            5 :         Array1D_bool lNumericBlanks;           // Logical array, numeric field input BLANK = .TRUE.
     336              : 
     337            5 :         auto &Zone = state.dataHeatBal->Zone;
     338            5 :         auto &Surface = state.dataSurface->Surface;
     339              : 
     340            5 :         Array1D_string VarFlowRadDesignNames;
     341            5 :         Array1D_string CFlowRadDesignNames;
     342              : 
     343            5 :         MaxAlphas = 0;
     344            5 :         MaxNumbers = 0;
     345              : 
     346            5 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(
     347              :             state, "ZoneHVAC:LowTemperatureRadiant:VariableFlow:Design", NumArgs, NumAlphas, NumNumbers);
     348            5 :         MaxAlphas = max(MaxAlphas, NumAlphas);
     349            5 :         MaxNumbers = max(MaxNumbers, NumNumbers);
     350              : 
     351            5 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(
     352              :             state, "ZoneHVAC:LowTemperatureRadiant:ConstantFlow:Design", NumArgs, NumAlphas, NumNumbers);
     353            5 :         MaxAlphas = max(MaxAlphas, NumAlphas);
     354            5 :         MaxNumbers = max(MaxNumbers, NumNumbers);
     355              : 
     356            5 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(
     357              :             state, "ZoneHVAC:LowTemperatureRadiant:VariableFlow", NumArgs, NumAlphas, NumNumbers);
     358            5 :         MaxAlphas = max(MaxAlphas, NumAlphas);
     359            5 :         MaxNumbers = max(MaxNumbers, NumNumbers);
     360              : 
     361            5 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(
     362              :             state, "ZoneHVAC:LowTemperatureRadiant:ConstantFlow", NumArgs, NumAlphas, NumNumbers);
     363            5 :         MaxAlphas = max(MaxAlphas, NumAlphas);
     364            5 :         MaxNumbers = max(MaxNumbers, NumNumbers);
     365              : 
     366            5 :         state.dataInputProcessing->inputProcessor->getObjectDefMaxArgs(
     367              :             state, "ZoneHVAC:LowTemperatureRadiant:Electric", NumArgs, NumAlphas, NumNumbers);
     368            5 :         MaxAlphas = max(MaxAlphas, NumAlphas);
     369            5 :         MaxNumbers = max(MaxNumbers, NumNumbers);
     370              : 
     371            5 :         Alphas.allocate(MaxAlphas);
     372            5 :         Numbers.dimension(MaxNumbers, 0.0);
     373            5 :         cAlphaFields.allocate(MaxAlphas);
     374            5 :         cNumericFields.allocate(MaxNumbers);
     375            5 :         lAlphaBlanks.dimension(MaxAlphas, true);
     376            5 :         lNumericBlanks.dimension(MaxNumbers, true);
     377              : 
     378           10 :         state.dataLowTempRadSys->NumOfHydrLowTempRadSys =
     379            5 :             state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "ZoneHVAC:LowTemperatureRadiant:VariableFlow");
     380           10 :         state.dataLowTempRadSys->NumOfCFloLowTempRadSys =
     381            5 :             state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "ZoneHVAC:LowTemperatureRadiant:ConstantFlow");
     382           10 :         state.dataLowTempRadSys->NumOfElecLowTempRadSys =
     383            5 :             state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "ZoneHVAC:LowTemperatureRadiant:Electric");
     384              : 
     385           10 :         state.dataLowTempRadSys->NumOfHydrLowTempRadSysDes =
     386            5 :             state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "ZoneHVAC:LowTemperatureRadiant:VariableFlow:Design");
     387           10 :         state.dataLowTempRadSys->NumOfCFloLowTempRadSysDes =
     388            5 :             state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, "ZoneHVAC:LowTemperatureRadiant:ConstantFlow:Design");
     389              : 
     390            5 :         state.dataLowTempRadSys->TotalNumOfRadSystems = state.dataLowTempRadSys->NumOfHydrLowTempRadSys +
     391            5 :                                                         state.dataLowTempRadSys->NumOfElecLowTempRadSys +
     392            5 :                                                         state.dataLowTempRadSys->NumOfCFloLowTempRadSys;
     393            5 :         state.dataLowTempRadSys->RadSysTypes.allocate(state.dataLowTempRadSys->TotalNumOfRadSystems);
     394            5 :         state.dataLowTempRadSys->LowTempRadUniqueNames.reserve(static_cast<unsigned>(state.dataLowTempRadSys->TotalNumOfRadSystems));
     395            5 :         state.dataLowTempRadSys->CheckEquipName.dimension(state.dataLowTempRadSys->TotalNumOfRadSystems, true);
     396              : 
     397            5 :         state.dataLowTempRadSys->HydrRadSys.allocate(state.dataLowTempRadSys->NumOfHydrLowTempRadSys);
     398            5 :         if (state.dataLowTempRadSys->NumOfHydrLowTempRadSys > 0) {
     399            4 :             auto *water = Fluid::GetWater(state);
     400            4 :             if (water == nullptr) {
     401            0 :                 ShowSevereError(state, "Hydronic radiant systems: no water property data found in input");
     402            0 :                 ErrorsFound = true;
     403              :             }
     404              : 
     405            8 :             for (auto &e : state.dataLowTempRadSys->HydrRadSys)
     406            4 :                 e.water = water;
     407              :         }
     408              : 
     409            5 :         state.dataLowTempRadSys->CFloRadSys.allocate(state.dataLowTempRadSys->NumOfCFloLowTempRadSys);
     410            5 :         if (state.dataLowTempRadSys->NumOfCFloLowTempRadSys > 0) {
     411            1 :             auto *water = Fluid::GetWater(state);
     412            1 :             if (water == nullptr) {
     413            0 :                 ShowSevereError(state, "Constant flow radiant systems: no water property data found in input");
     414            0 :                 ErrorsFound = true;
     415              :             }
     416              : 
     417            2 :             for (auto &e : state.dataLowTempRadSys->CFloRadSys)
     418            1 :                 e.water = water;
     419              :         }
     420              : 
     421            5 :         state.dataLowTempRadSys->ElecRadSys.allocate(state.dataLowTempRadSys->NumOfElecLowTempRadSys);
     422            5 :         state.dataLowTempRadSys->ElecRadSysNumericFields.allocate(state.dataLowTempRadSys->NumOfElecLowTempRadSys);
     423              : 
     424            5 :         state.dataLowTempRadSys->HydronicRadiantSysNumericFields.allocate(state.dataLowTempRadSys->NumOfHydrLowTempRadSys);
     425            5 :         state.dataLowTempRadSys->HydronicRadiantSysDesign.allocate(state.dataLowTempRadSys->NumOfHydrLowTempRadSysDes);
     426            5 :         VarFlowRadDesignNames.allocate(state.dataLowTempRadSys->NumOfHydrLowTempRadSysDes);
     427              : 
     428            5 :         state.dataLowTempRadSys->CflowRadiantSysDesign.allocate(state.dataLowTempRadSys->NumOfCFloLowTempRadSysDes);
     429            5 :         CFlowRadDesignNames.allocate(state.dataLowTempRadSys->NumOfCFloLowTempRadSysDes);
     430              : 
     431              :         // make sure data is gotten for surface lists
     432            5 :         GetNumberOfSurfaceLists(state);
     433              : 
     434              :         // Obtain all of the design data related to hydronic low temperature radiant systems...
     435            5 :         CurrentModuleObject = "ZoneHVAC:LowTemperatureRadiant:VariableFlow:Design";
     436            9 :         for (Item = 1; Item <= state.dataLowTempRadSys->NumOfHydrLowTempRadSysDes; ++Item) {
     437              : 
     438            4 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
     439              :                                                                      CurrentModuleObject,
     440              :                                                                      Item,
     441              :                                                                      Alphas,
     442              :                                                                      NumAlphas,
     443              :                                                                      Numbers,
     444              :                                                                      NumNumbers,
     445              :                                                                      IOStatus,
     446              :                                                                      lNumericBlanks,
     447              :                                                                      lAlphaBlanks,
     448              :                                                                      cAlphaFields,
     449              :                                                                      cNumericFields);
     450              : 
     451            4 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
     452              : 
     453            4 :             state.dataLowTempRadSys->HydronicRadiantSysDesign(Item).FieldNames.allocate(NumNumbers);
     454            4 :             state.dataLowTempRadSys->HydronicRadiantSysDesign(Item).FieldNames = "";
     455            4 :             state.dataLowTempRadSys->HydronicRadiantSysDesign(Item).FieldNames = cNumericFields;
     456            4 :             GlobalNames::VerifyUniqueInterObjectName(
     457            8 :                 state, state.dataLowTempRadSys->LowTempRadUniqueNames, Alphas(1), CurrentModuleObject, cAlphaFields(1), ErrorsFound);
     458              : 
     459            4 :             auto &thisRadSysDesign = state.dataLowTempRadSys->HydronicRadiantSysDesign(Item);
     460              : 
     461              :             // General user input data
     462            4 :             thisRadSysDesign.designName = Alphas(1);
     463              : 
     464            4 :             if (lAlphaBlanks(2)) {
     465            0 :                 thisRadSysDesign.FluidToSlabHeatTransfer = FluidToSlabHeatTransferType::ConvectionOnly;
     466            4 :             } else if ((thisRadSysDesign.FluidToSlabHeatTransfer = static_cast<FluidToSlabHeatTransferType>(
     467            4 :                             getEnumValue(fluidToSlabHeatTransferTypeNamesUC, Alphas(2)))) == FluidToSlabHeatTransferType::Invalid) {
     468            0 :                 ShowWarningInvalidKey(state, eoh, cAlphaFields(2), Alphas(2), "ConvectionOnly");
     469            0 :                 thisRadSysDesign.FluidToSlabHeatTransfer = FluidToSlabHeatTransferType::ConvectionOnly;
     470              :             }
     471              : 
     472            4 :             thisRadSysDesign.TubeDiameterInner = Numbers(1);
     473            4 :             thisRadSysDesign.TubeDiameterOuter = Numbers(2);
     474              : 
     475            4 :             thisRadSysDesign.VarFlowTubeConductivity = Numbers(3);
     476              : 
     477              :             // Process the temperature control type
     478            4 :             if (lAlphaBlanks(3)) {
     479            0 :                 thisRadSysDesign.VarFlowControlType = CtrlType::MAT;
     480            4 :             } else if ((thisRadSysDesign.VarFlowControlType = static_cast<CtrlType>(getEnumValue(ctrlTypeNamesUC, Alphas(3)))) == CtrlType::Invalid) {
     481            0 :                 ShowWarningInvalidKey(state, eoh, cAlphaFields(3), Alphas(3), "MeanAirTemperature");
     482            0 :                 thisRadSysDesign.VarFlowControlType = CtrlType::MAT;
     483              :             }
     484              : 
     485              :             // Process the setpoint type
     486            4 :             if (lAlphaBlanks(4)) {
     487            0 :                 thisRadSysDesign.VarFlowSetpointType = SetpointType::HalfFlowPower;
     488            4 :             } else if ((thisRadSysDesign.VarFlowSetpointType = static_cast<SetpointType>(getEnumValue(setpointTypeNamesUC, Alphas(4)))) ==
     489              :                        SetpointType::Invalid) {
     490            0 :                 ShowWarningInvalidKey(state, eoh, cAlphaFields(4), Alphas(4), "HalfFlowPower");
     491            0 :                 thisRadSysDesign.VarFlowSetpointType = SetpointType::HalfFlowPower;
     492              :             }
     493              : 
     494              :             // Refactor everything below to Alphas as HCMethod, etc
     495              : 
     496              :             // Determine Low Temp Radiant heating design capacity sizing method
     497            4 :             thisRadSysDesign.DesignHeatingCapMethodInput = Alphas(5);
     498            4 :             if (Util::SameString(thisRadSysDesign.DesignHeatingCapMethodInput, "HeatingDesignCapacity")) {
     499            1 :                 thisRadSysDesign.DesignHeatingCapMethod = HeatingDesignCapacity;
     500            3 :             } else if (Util::SameString(thisRadSysDesign.DesignHeatingCapMethodInput, "CapacityPerFloorArea")) {
     501            0 :                 thisRadSysDesign.DesignHeatingCapMethod = CapacityPerFloorArea;
     502            0 :                 if (!lNumericBlanks(4)) {
     503            0 :                     thisRadSysDesign.DesignScaledHeatingCapacity = Numbers(4);
     504            0 :                     if (thisRadSysDesign.DesignScaledHeatingCapacity <= 0.0) {
     505            0 :                         ShowSevereError(state, format("{} = {}", CurrentModuleObject, thisRadSysDesign.designName));
     506            0 :                         ShowContinueError(state, format("Input for {} = {}", cAlphaFields(5), thisRadSysDesign.DesignHeatingCapMethodInput));
     507            0 :                         ShowContinueError(state, format("Illegal {} = {:.7T}", cNumericFields(4), Numbers(4)));
     508            0 :                         ErrorsFound = true;
     509            0 :                     } else if (thisRadSysDesign.DesignScaledHeatingCapacity == AutoSize) {
     510            0 :                         ShowSevereError(state, format("{} = {}", CurrentModuleObject, thisRadSysDesign.designName));
     511            0 :                         ShowContinueError(state, format("Input for {} = {}", cAlphaFields(5), thisRadSysDesign.DesignHeatingCapMethodInput));
     512            0 :                         ShowContinueError(state, format("Illegal {} = Autosize", cNumericFields(4)));
     513            0 :                         ErrorsFound = true;
     514              :                     }
     515              :                 } else {
     516            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, thisRadSysDesign.Name));
     517            0 :                     ShowContinueError(state, format("Input for {} = {}", cAlphaFields(5), thisRadSysDesign.DesignHeatingCapMethodInput));
     518            0 :                     ShowContinueError(state, format("Blank field not allowed for {}", cNumericFields(4)));
     519            0 :                     ErrorsFound = true;
     520              :                 }
     521            3 :             } else if (Util::SameString(thisRadSysDesign.DesignHeatingCapMethodInput, "FractionOfAutosizedHeatingCapacity")) {
     522            3 :                 thisRadSysDesign.DesignHeatingCapMethod = FractionOfAutosizedHeatingCapacity;
     523            3 :                 if (!lNumericBlanks(5)) {
     524            3 :                     thisRadSysDesign.DesignScaledHeatingCapacity = Numbers(5);
     525            3 :                     if (thisRadSysDesign.DesignScaledHeatingCapacity < 0.0) {
     526            0 :                         ShowSevereError(state, format("{} = {}", CurrentModuleObject, thisRadSysDesign.designName));
     527            0 :                         ShowContinueError(state, format("Illegal {} = {:.7T}", cNumericFields(5), Numbers(5)));
     528            0 :                         ErrorsFound = true;
     529              :                     }
     530              :                 } else {
     531            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, thisRadSysDesign.designName));
     532            0 :                     ShowContinueError(state, format("Input for {} = {}", cAlphaFields(5), thisRadSysDesign.DesignHeatingCapMethodInput));
     533            0 :                     ShowContinueError(state, format("Blank field not allowed for {}", cNumericFields(5)));
     534            0 :                     ErrorsFound = true;
     535              :                 }
     536              :             } else {
     537            0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, thisRadSysDesign.designName));
     538            0 :                 ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(5), thisRadSysDesign.DesignHeatingCapMethodInput));
     539            0 :                 ErrorsFound = true;
     540              :             }
     541              : 
     542            4 :             thisRadSysDesign.HotThrottlRange = Numbers(6);
     543              : 
     544            4 :             if (lAlphaBlanks(6)) {
     545            4 :             } else if ((thisRadSysDesign.heatSetptSched = Sched::GetSchedule(state, Alphas(6))) == nullptr) {
     546            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(6), Alphas(6));
     547            0 :                 ErrorsFound = true;
     548              :             }
     549              : 
     550              :             // Determine Low Temp Radiant cooling design capacity sizing method
     551            4 :             thisRadSysDesign.DesignCoolingCapMethodInput = Alphas(7);
     552            4 :             if (Util::SameString(thisRadSysDesign.DesignCoolingCapMethodInput, "CoolingDesignCapacity")) {
     553            1 :                 thisRadSysDesign.DesignCoolingCapMethod = CoolingDesignCapacity;
     554            3 :             } else if (Util::SameString(thisRadSysDesign.DesignCoolingCapMethodInput, "CapacityPerFloorArea")) {
     555            2 :                 thisRadSysDesign.DesignCoolingCapMethod = CapacityPerFloorArea;
     556            2 :                 if (!lNumericBlanks(7)) {
     557            2 :                     thisRadSysDesign.DesignScaledCoolingCapacity = Numbers(7);
     558            2 :                     if (thisRadSysDesign.DesignScaledCoolingCapacity <= 0.0) {
     559            1 :                         ShowSevereError(state, format("{} = {}", CurrentModuleObject, thisRadSysDesign.designName));
     560            1 :                         ShowContinueError(state, format("Input for {} = {}", cAlphaFields(7), thisRadSysDesign.DesignCoolingCapMethodInput));
     561            1 :                         ShowContinueError(state, format("Illegal {} = {:.7T}", cNumericFields(7), thisRadSysDesign.DesignScaledCoolingCapacity));
     562            1 :                         ErrorsFound = true;
     563            1 :                     } else if (thisRadSysDesign.DesignScaledCoolingCapacity == AutoSize) {
     564            0 :                         ShowSevereError(state, format("{} = {}", CurrentModuleObject, thisRadSysDesign.designName));
     565            0 :                         ShowContinueError(state, format("Input for {} = {}", cAlphaFields(7), thisRadSysDesign.DesignCoolingCapMethodInput));
     566            0 :                         ShowContinueError(state, format("Illegal {} = Autosize", cNumericFields(7)));
     567            0 :                         ErrorsFound = true;
     568              :                     }
     569              :                 } else {
     570            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, thisRadSysDesign.designName));
     571            0 :                     ShowContinueError(state, format("Input for {} = {}", cAlphaFields(7), thisRadSysDesign.DesignCoolingCapMethodInput));
     572            0 :                     ShowContinueError(state, format("Blank field not allowed for {}", cNumericFields(7)));
     573            0 :                     ErrorsFound = true;
     574              :                 }
     575            1 :             } else if (Util::SameString(thisRadSysDesign.DesignCoolingCapMethodInput, "FractionOfAutosizedCoolingCapacity")) {
     576            1 :                 thisRadSysDesign.DesignCoolingCapMethod = FractionOfAutosizedCoolingCapacity;
     577            1 :                 if (!lNumericBlanks(8)) {
     578            1 :                     thisRadSysDesign.DesignScaledCoolingCapacity = Numbers(8);
     579            1 :                     if (thisRadSysDesign.DesignScaledCoolingCapacity < 0.0) {
     580            0 :                         ShowSevereError(state, format("{} = {}", CurrentModuleObject, thisRadSysDesign.designName));
     581            0 :                         ShowContinueError(state, format("Illegal {} = {:.7T}", cNumericFields(8), Numbers(8)));
     582            0 :                         ErrorsFound = true;
     583              :                     }
     584              :                 } else {
     585            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, thisRadSysDesign.designName));
     586            0 :                     ShowContinueError(state, format("Input for {} = {}", cAlphaFields(7), thisRadSysDesign.DesignCoolingCapMethodInput));
     587            0 :                     ShowContinueError(state, format("Blank field not allowed for {}", cNumericFields(8)));
     588            0 :                     ErrorsFound = true;
     589              :                 }
     590              :             } else {
     591            0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, thisRadSysDesign.designName));
     592            0 :                 ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(7), thisRadSysDesign.DesignCoolingCapMethodInput));
     593            0 :                 ErrorsFound = true;
     594              :             }
     595              : 
     596            4 :             thisRadSysDesign.ColdThrottlRange = Numbers(9);
     597              : 
     598            4 :             if (lAlphaBlanks(8)) {
     599            4 :             } else if ((thisRadSysDesign.coolSetptSched = Sched::GetSchedule(state, Alphas(8))) == nullptr) {
     600            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(8), Alphas(8));
     601            0 :                 ErrorsFound = true;
     602              :             }
     603              : 
     604            4 :             if (lAlphaBlanks(9)) {
     605            3 :                 thisRadSysDesign.condCtrlType = CondCtrlType::SimpleOff;
     606            1 :             } else if ((thisRadSysDesign.condCtrlType = static_cast<CondCtrlType>(getEnumValue(condCtrlTypeNamesUC, Alphas(9)))) ==
     607              :                        CondCtrlType::Invalid) {
     608            0 :                 ShowWarningInvalidKey(state, eoh, cAlphaFields(9), Alphas(9), "SimpleOff");
     609            0 :                 thisRadSysDesign.condCtrlType = CondCtrlType::SimpleOff;
     610              :             }
     611              : 
     612            4 :             thisRadSysDesign.CondDewPtDeltaT = Numbers(10);
     613              : 
     614            4 :             if (lAlphaBlanks(10)) {
     615            0 :             } else if ((thisRadSysDesign.changeoverDelaySched = Sched::GetSchedule(state, Alphas(10))) == nullptr) {
     616            0 :                 ShowWarningItemNotFound(state, eoh, cAlphaFields(10), Alphas(10), "No changeover delay will be used for this radiant system.");
     617              :             }
     618              : 
     619            4 :             VarFlowRadDesignNames(Item) = Alphas(1);
     620              :         }
     621              : 
     622              :         // Obtain all of the user data related to hydronic low temperature radiant systems...
     623            5 :         BaseNum = 0;
     624            5 :         CurrentModuleObject = "ZoneHVAC:LowTemperatureRadiant:VariableFlow";
     625            9 :         for (Item = 1; Item <= state.dataLowTempRadSys->NumOfHydrLowTempRadSys; ++Item) {
     626              : 
     627            4 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
     628              :                                                                      CurrentModuleObject,
     629              :                                                                      Item,
     630              :                                                                      Alphas,
     631              :                                                                      NumAlphas,
     632              :                                                                      Numbers,
     633              :                                                                      NumNumbers,
     634              :                                                                      IOStatus,
     635              :                                                                      lNumericBlanks,
     636              :                                                                      lAlphaBlanks,
     637              :                                                                      cAlphaFields,
     638              :                                                                      cNumericFields);
     639              : 
     640            4 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
     641              : 
     642            4 :             state.dataLowTempRadSys->HydronicRadiantSysNumericFields(Item).FieldNames.allocate(NumNumbers);
     643            4 :             state.dataLowTempRadSys->HydronicRadiantSysNumericFields(Item).FieldNames = "";
     644            4 :             state.dataLowTempRadSys->HydronicRadiantSysNumericFields(Item).FieldNames = cNumericFields;
     645            4 :             GlobalNames::VerifyUniqueInterObjectName(
     646            8 :                 state, state.dataLowTempRadSys->LowTempRadUniqueNames, Alphas(1), CurrentModuleObject, cAlphaFields(1), ErrorsFound);
     647              : 
     648            4 :             ++BaseNum;
     649            4 :             state.dataLowTempRadSys->RadSysTypes(BaseNum).Name = Alphas(1);
     650            4 :             state.dataLowTempRadSys->RadSysTypes(BaseNum).systemType = SystemType::Hydronic;
     651              : 
     652            4 :             auto &thisRadSys = state.dataLowTempRadSys->HydrRadSys(Item);
     653              : 
     654              :             // General user input data
     655            4 :             thisRadSys.Name = Alphas(1);
     656              : 
     657            4 :             thisRadSys.designObjectName = Alphas(2);
     658            4 :             thisRadSys.DesignObjectPtr = Util::FindItemInList(thisRadSys.designObjectName, VarFlowRadDesignNames);
     659            4 :             VarFlowRadDesignData variableFlowDesignDataObject{state.dataLowTempRadSys->HydronicRadiantSysDesign(
     660            4 :                 thisRadSys.DesignObjectPtr)}; // Contains the data for variable flow hydronic systems
     661              : 
     662            4 :             if (lAlphaBlanks(3)) {
     663            0 :                 thisRadSys.availSched = Sched::GetScheduleAlwaysOn(state);
     664            4 :             } else if ((thisRadSys.availSched = Sched::GetSchedule(state, Alphas(3))) == nullptr) {
     665            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(3), Alphas(3));
     666            0 :                 ErrorsFound = true;
     667              :             }
     668              : 
     669            4 :             thisRadSys.ZoneName = Alphas(4);
     670            4 :             thisRadSys.ZonePtr = Util::FindItemInList(Alphas(4), Zone);
     671            4 :             if (thisRadSys.ZonePtr == 0) {
     672            0 :                 ShowSevereError(state, format("{}Invalid {} = {}", RoutineName, cAlphaFields(3), Alphas(4)));
     673            0 :                 ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, Alphas(1)));
     674            0 :                 ErrorsFound = true;
     675              :             }
     676              : 
     677            4 :             thisRadSys.SurfListName = Alphas(5);
     678            4 :             SurfListNum = 0;
     679            4 :             if (state.dataSurfLists->NumOfSurfaceLists > 0)
     680            1 :                 SurfListNum = Util::FindItemInList(thisRadSys.SurfListName, state.dataSurfLists->SurfList);
     681            4 :             if (SurfListNum > 0) { // Found a valid surface list
     682            1 :                 thisRadSys.NumOfSurfaces = state.dataSurfLists->SurfList(SurfListNum).NumOfSurfaces;
     683            1 :                 thisRadSys.SurfacePtr.allocate(thisRadSys.NumOfSurfaces);
     684            1 :                 thisRadSys.SurfaceName.allocate(thisRadSys.NumOfSurfaces);
     685            1 :                 thisRadSys.SurfaceFrac.allocate(thisRadSys.NumOfSurfaces);
     686            1 :                 thisRadSys.NumCircuits.allocate(thisRadSys.NumOfSurfaces);
     687            3 :                 for (SurfNum = 1; SurfNum <= state.dataSurfLists->SurfList(SurfListNum).NumOfSurfaces; ++SurfNum) {
     688            2 :                     thisRadSys.SurfacePtr(SurfNum) = state.dataSurfLists->SurfList(SurfListNum).SurfPtr(SurfNum);
     689            2 :                     thisRadSys.SurfaceName(SurfNum) = state.dataSurfLists->SurfList(SurfListNum).SurfName(SurfNum);
     690            2 :                     thisRadSys.SurfaceFrac(SurfNum) = state.dataSurfLists->SurfList(SurfListNum).SurfFlowFrac(SurfNum);
     691            2 :                     if (thisRadSys.SurfacePtr(SurfNum) > 0) {
     692            2 :                         state.dataSurface->surfIntConv(thisRadSys.SurfacePtr(SurfNum)).hasActiveInIt = true;
     693              :                     }
     694              :                 }
     695              :             } else { // User entered a single surface name rather than a surface list
     696            3 :                 thisRadSys.NumOfSurfaces = 1;
     697            3 :                 thisRadSys.SurfacePtr.allocate(thisRadSys.NumOfSurfaces);
     698            3 :                 thisRadSys.SurfaceName.allocate(thisRadSys.NumOfSurfaces);
     699            3 :                 thisRadSys.SurfaceFrac.allocate(thisRadSys.NumOfSurfaces);
     700            3 :                 thisRadSys.NumCircuits.allocate(thisRadSys.NumOfSurfaces);
     701            3 :                 thisRadSys.SurfaceName(1) = thisRadSys.SurfListName;
     702            3 :                 thisRadSys.SurfacePtr(1) = Util::FindItemInList(thisRadSys.SurfaceName(1), Surface);
     703            3 :                 thisRadSys.SurfaceFrac(1) = 1.0;
     704            3 :                 thisRadSys.NumCircuits(1) = 0.0;
     705              :                 // Error checking for single surfaces
     706            3 :                 if (thisRadSys.SurfacePtr(1) == 0) {
     707            0 :                     ShowSevereError(state, format("{}Invalid {} = {}", RoutineName, cAlphaFields(5), Alphas(5)));
     708            0 :                     ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, Alphas(1)));
     709            0 :                     ErrorsFound = true;
     710            3 :                 } else if (state.dataSurface->SurfIsRadSurfOrVentSlabOrPool(thisRadSys.SurfacePtr(1))) {
     711            0 :                     ShowSevereError(state, format("{}{}=\"{}\", Invalid Surface", RoutineName, CurrentModuleObject, Alphas(1)));
     712            0 :                     ShowContinueError(state,
     713            0 :                                       format("{}=\"{}\" has been used in another radiant system or ventilated slab.", cAlphaFields(5), Alphas(5)));
     714            0 :                     ErrorsFound = true;
     715              :                 }
     716            3 :                 if (thisRadSys.SurfacePtr(1) != 0) {
     717            3 :                     state.dataSurface->surfIntConv(thisRadSys.SurfacePtr(1)).hasActiveInIt = true;
     718            3 :                     state.dataSurface->surfIntConv(thisRadSys.SurfacePtr(1)).hasActiveInIt = true; // Ummmm ... what?
     719              :                 }
     720              :             }
     721              : 
     722              :             // Error checking for zones and construction information
     723            4 :             thisRadSys.errorCheckZonesAndConstructions(state, ErrorsFound);
     724              : 
     725            4 :             thisRadSys.TubeLength = Numbers(1);
     726              : 
     727              :             // Determine Low Temp Radiant heating design capacity sizing method
     728            4 :             if (variableFlowDesignDataObject.DesignHeatingCapMethod == HeatingDesignCapacity) {
     729            1 :                 thisRadSys.HeatingCapMethod = HeatingDesignCapacity;
     730            1 :                 if (!lNumericBlanks(2)) {
     731            1 :                     thisRadSys.ScaledHeatingCapacity = Numbers(2);
     732            1 :                     if (thisRadSys.ScaledHeatingCapacity < 0.0 && thisRadSys.ScaledHeatingCapacity != AutoSize) {
     733            0 :                         ShowSevereError(state, format("{} = {}", CurrentModuleObject, thisRadSys.Name));
     734            0 :                         ShowContinueError(state, format("Illegal {} = {:.7T}", cNumericFields(2), Numbers(2)));
     735            0 :                         ErrorsFound = true;
     736              :                     }
     737              :                 } else {
     738            0 :                     if ((!lAlphaBlanks(6)) || (!lAlphaBlanks(7))) {
     739            0 :                         ShowSevereError(state, format("{} = {}", CurrentModuleObject, thisRadSys.Name));
     740            0 :                         ShowContinueError(state, "Input for Heating Design Capacity Method = HeatingDesignCapacity");
     741            0 :                         ShowContinueError(state, format("Blank field not allowed for {}", cNumericFields(2)));
     742            0 :                         ErrorsFound = true;
     743              :                     }
     744              :                 }
     745            3 :             } else if (variableFlowDesignDataObject.DesignHeatingCapMethod == CapacityPerFloorArea) {
     746            0 :                 thisRadSys.HeatingCapMethod = CapacityPerFloorArea;
     747            0 :                 thisRadSys.ScaledHeatingCapacity = variableFlowDesignDataObject.DesignScaledHeatingCapacity;
     748            3 :             } else if (variableFlowDesignDataObject.DesignHeatingCapMethod == FractionOfAutosizedHeatingCapacity) {
     749            3 :                 thisRadSys.HeatingCapMethod = FractionOfAutosizedHeatingCapacity;
     750            3 :                 thisRadSys.ScaledHeatingCapacity = variableFlowDesignDataObject.DesignScaledHeatingCapacity;
     751              :             }
     752              : 
     753              :             // Heating user input data
     754            4 :             thisRadSys.WaterVolFlowMaxHeat = Numbers(3);
     755              : 
     756            4 :             thisRadSys.HotWaterInNode = GetOnlySingleNode(state,
     757            4 :                                                           Alphas(6),
     758              :                                                           ErrorsFound,
     759              :                                                           DataLoopNode::ConnectionObjectType::ZoneHVACLowTemperatureRadiantVariableFlow,
     760            4 :                                                           Alphas(1),
     761              :                                                           DataLoopNode::NodeFluidType::Water,
     762              :                                                           DataLoopNode::ConnectionType::Inlet,
     763              :                                                           NodeInputManager::CompFluidStream::Primary,
     764              :                                                           ObjectIsNotParent);
     765              : 
     766            4 :             thisRadSys.HotWaterOutNode = GetOnlySingleNode(state,
     767            4 :                                                            Alphas(7),
     768              :                                                            ErrorsFound,
     769              :                                                            DataLoopNode::ConnectionObjectType::ZoneHVACLowTemperatureRadiantVariableFlow,
     770            4 :                                                            Alphas(1),
     771              :                                                            DataLoopNode::NodeFluidType::Water,
     772              :                                                            DataLoopNode::ConnectionType::Outlet,
     773              :                                                            NodeInputManager::CompFluidStream::Primary,
     774              :                                                            ObjectIsNotParent);
     775              : 
     776            4 :             if ((!lAlphaBlanks(6)) || (!lAlphaBlanks(7))) {
     777            6 :                 TestCompSet(state, CurrentModuleObject, Alphas(1), Alphas(6), Alphas(7), "Hot Water Nodes");
     778              :             }
     779            7 :             if ((thisRadSys.WaterVolFlowMaxHeat == AutoSize) &&
     780            3 :                 (lAlphaBlanks(6) || lAlphaBlanks(7) || (thisRadSys.HotWaterInNode <= 0) || (thisRadSys.HotWaterOutNode <= 0) ||
     781            3 :                  (variableFlowDesignDataObject.heatSetptSched == nullptr))) {
     782            0 :                 ShowSevereError(state, "Hydronic radiant systems may not be autosized without specification of nodes or schedules.");
     783            0 :                 ShowContinueError(state, format("Occurs in {} (heating input) = {}", CurrentModuleObject, Alphas(1)));
     784            0 :                 ErrorsFound = true;
     785              :             }
     786              : 
     787              :             // Determine Low Temp Radiant cooling design capacity sizing method
     788            4 :             if (variableFlowDesignDataObject.DesignCoolingCapMethod == CoolingDesignCapacity) {
     789            1 :                 thisRadSys.CoolingCapMethod = CoolingDesignCapacity;
     790            1 :                 if (!lNumericBlanks(4)) {
     791            1 :                     thisRadSys.ScaledCoolingCapacity = Numbers(4);
     792            1 :                     if (thisRadSys.ScaledCoolingCapacity < 0.0 && thisRadSys.ScaledCoolingCapacity != AutoSize) {
     793            0 :                         ShowSevereError(state, format("{} = {}", CurrentModuleObject, thisRadSys.Name));
     794            0 :                         ShowContinueError(state, format("Illegal {} = {:.7T}", cNumericFields(4), Numbers(4)));
     795            0 :                         ErrorsFound = true;
     796              :                     }
     797              :                 } else {
     798            0 :                     if ((!lAlphaBlanks(8)) || (!lAlphaBlanks(9))) {
     799            0 :                         ShowSevereError(state, format("{} = {}", CurrentModuleObject, thisRadSys.Name));
     800            0 :                         ShowContinueError(state, "Input for Cooling Design Capacity Method = CoolingDesignCapacity");
     801            0 :                         ShowContinueError(state, format("Blank field not allowed for {}", cNumericFields(4)));
     802            0 :                         ErrorsFound = true;
     803              :                     }
     804              :                 }
     805            3 :             } else if (variableFlowDesignDataObject.DesignCoolingCapMethod == CapacityPerFloorArea) {
     806            2 :                 thisRadSys.CoolingCapMethod = CapacityPerFloorArea;
     807            2 :                 thisRadSys.ScaledCoolingCapacity = variableFlowDesignDataObject.DesignScaledCoolingCapacity;
     808            1 :             } else if (variableFlowDesignDataObject.DesignCoolingCapMethod == FractionOfAutosizedCoolingCapacity) {
     809            1 :                 thisRadSys.CoolingCapMethod = FractionOfAutosizedCoolingCapacity;
     810            1 :                 thisRadSys.ScaledCoolingCapacity = variableFlowDesignDataObject.DesignScaledCoolingCapacity;
     811              :             }
     812              : 
     813              :             // Cooling user input data
     814            4 :             thisRadSys.WaterVolFlowMaxCool = Numbers(5);
     815              : 
     816            4 :             thisRadSys.ColdWaterInNode = GetOnlySingleNode(state,
     817            4 :                                                            Alphas(8),
     818              :                                                            ErrorsFound,
     819              :                                                            DataLoopNode::ConnectionObjectType::ZoneHVACLowTemperatureRadiantVariableFlow,
     820            4 :                                                            Alphas(1),
     821              :                                                            DataLoopNode::NodeFluidType::Water,
     822              :                                                            DataLoopNode::ConnectionType::Inlet,
     823              :                                                            NodeInputManager::CompFluidStream::Secondary,
     824              :                                                            ObjectIsNotParent);
     825              : 
     826            4 :             thisRadSys.ColdWaterOutNode = GetOnlySingleNode(state,
     827            4 :                                                             Alphas(9),
     828              :                                                             ErrorsFound,
     829              :                                                             DataLoopNode::ConnectionObjectType::ZoneHVACLowTemperatureRadiantVariableFlow,
     830            4 :                                                             Alphas(1),
     831              :                                                             DataLoopNode::NodeFluidType::Water,
     832              :                                                             DataLoopNode::ConnectionType::Outlet,
     833              :                                                             NodeInputManager::CompFluidStream::Secondary,
     834              :                                                             ObjectIsNotParent);
     835              : 
     836            4 :             if ((!lAlphaBlanks(8)) || (!lAlphaBlanks(9))) {
     837            8 :                 TestCompSet(state, CurrentModuleObject, Alphas(1), Alphas(8), Alphas(9), "Chilled Water Nodes");
     838              :             }
     839              : 
     840            4 :             if (lAlphaBlanks(10)) {
     841            3 :                 thisRadSys.NumCircCalcMethod = CircuitCalc::OneCircuit;
     842            1 :             } else if ((thisRadSys.NumCircCalcMethod = static_cast<CircuitCalc>(getEnumValue(circuitCalcNamesUC, Alphas(10)))) ==
     843              :                        CircuitCalc::Invalid) {
     844            0 :                 ShowWarningInvalidKey(state, eoh, cAlphaFields(10), Alphas(10), "OnePerSurface");
     845            0 :                 thisRadSys.NumCircCalcMethod = CircuitCalc::OneCircuit;
     846              :             }
     847              : 
     848            4 :             thisRadSys.changeoverDelaySched = variableFlowDesignDataObject.changeoverDelaySched;
     849              : 
     850            4 :             thisRadSys.CircLength = Numbers(6);
     851              : 
     852            8 :             if ((thisRadSys.WaterVolFlowMaxCool == AutoSize) &&
     853            4 :                 (variableFlowDesignDataObject.DesignCoolingCapMethod == 0 || lAlphaBlanks(8) || lAlphaBlanks(9) ||
     854            4 :                  (thisRadSys.ColdWaterInNode <= 0) || (thisRadSys.ColdWaterOutNode <= 0) ||
     855            4 :                  (variableFlowDesignDataObject.coolSetptSched == nullptr))) {
     856            0 :                 ShowSevereError(state, "Hydronic radiant systems may not be autosized without specification of nodes or schedules");
     857            0 :                 ShowContinueError(state, format("Occurs in {} (cooling input) ={}", CurrentModuleObject, Alphas(1)));
     858            0 :                 ErrorsFound = true;
     859              :             }
     860            4 :         }
     861              : 
     862              :         // Obtain all of the design data related to Constant flow low temperature radiant systems...
     863            5 :         CurrentModuleObject = "ZoneHVAC:LowTemperatureRadiant:ConstantFlow:Design";
     864            6 :         for (Item = 1; Item <= state.dataLowTempRadSys->NumOfCFloLowTempRadSysDes; ++Item) {
     865              : 
     866            1 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
     867              :                                                                      CurrentModuleObject,
     868              :                                                                      Item,
     869              :                                                                      Alphas,
     870              :                                                                      NumAlphas,
     871              :                                                                      Numbers,
     872              :                                                                      NumNumbers,
     873              :                                                                      IOStatus,
     874              :                                                                      lNumericBlanks,
     875              :                                                                      lAlphaBlanks,
     876              :                                                                      cAlphaFields,
     877              :                                                                      cNumericFields);
     878              : 
     879            1 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
     880              : 
     881            1 :             state.dataLowTempRadSys->CflowRadiantSysDesign(Item).FieldNames.allocate(NumNumbers);
     882            1 :             state.dataLowTempRadSys->CflowRadiantSysDesign(Item).FieldNames = "";
     883            1 :             state.dataLowTempRadSys->CflowRadiantSysDesign(Item).FieldNames = cNumericFields;
     884            1 :             GlobalNames::VerifyUniqueInterObjectName(
     885            2 :                 state, state.dataLowTempRadSys->LowTempRadUniqueNames, Alphas(1), CurrentModuleObject, cAlphaFields(1), ErrorsFound);
     886              : 
     887            1 :             auto &thisRadSysDesign = state.dataLowTempRadSys->CflowRadiantSysDesign(Item);
     888              : 
     889              :             // General user input data
     890            1 :             thisRadSysDesign.designName = Alphas(1);
     891              : 
     892            1 :             if (lAlphaBlanks(2)) {
     893            0 :                 thisRadSysDesign.FluidToSlabHeatTransfer = FluidToSlabHeatTransferType::ConvectionOnly;
     894            1 :             } else if ((thisRadSysDesign.FluidToSlabHeatTransfer = static_cast<FluidToSlabHeatTransferType>(
     895            1 :                             getEnumValue(fluidToSlabHeatTransferTypeNamesUC, Alphas(2)))) == FluidToSlabHeatTransferType::Invalid) {
     896            0 :                 ShowWarningInvalidKey(state, eoh, cAlphaFields(2), Alphas(2), "ConvectionOnly");
     897            0 :                 thisRadSysDesign.FluidToSlabHeatTransfer = FluidToSlabHeatTransferType::ConvectionOnly;
     898              :             }
     899              : 
     900            1 :             thisRadSysDesign.TubeDiameterInner = Numbers(1);
     901            1 :             thisRadSysDesign.TubeDiameterOuter = Numbers(2);
     902            1 :             thisRadSysDesign.ConstFlowTubeConductivity = Numbers(3);
     903              : 
     904              :             // Process the temperature control type
     905            1 :             if (lAlphaBlanks(3)) {
     906            0 :                 thisRadSysDesign.ConstFlowControlType = CtrlType::MAT;
     907            1 :             } else if ((thisRadSysDesign.ConstFlowControlType = static_cast<CtrlType>(getEnumValue(ctrlTypeNamesUC, Alphas(3)))) ==
     908              :                        CtrlType::Invalid) {
     909            0 :                 ShowWarningInvalidKey(state, eoh, cAlphaFields(3), Alphas(3), "MeanAirTemperature");
     910            0 :                 thisRadSysDesign.ConstFlowControlType = CtrlType::MAT;
     911            1 :             } else if (thisRadSysDesign.ConstFlowControlType == CtrlType::RunningMeanODB) {
     912            0 :                 state.dataLowTempRadSys->anyRadiantSystemUsingRunningMeanAverage = true;
     913              :             }
     914              : 
     915            1 :             thisRadSysDesign.runningMeanOutdoorAirTemperatureWeightingFactor = Numbers(4);
     916            1 :             thisRadSysDesign.MotorEffic = Numbers(5);
     917            1 :             thisRadSysDesign.FracMotorLossToFluid = Numbers(6);
     918              : 
     919            1 :             if (lAlphaBlanks(4)) {
     920            0 :                 thisRadSysDesign.condCtrlType = CondCtrlType::SimpleOff;
     921            1 :             } else if ((thisRadSysDesign.condCtrlType = static_cast<CondCtrlType>(getEnumValue(condCtrlTypeNamesUC, Alphas(4)))) ==
     922              :                        CondCtrlType::Invalid) {
     923            0 :                 ShowWarningInvalidKey(state, eoh, cAlphaFields(4), Alphas(4), "SimpleOff");
     924            0 :                 thisRadSysDesign.condCtrlType = CondCtrlType::SimpleOff;
     925              :             }
     926              : 
     927            1 :             thisRadSysDesign.CondDewPtDeltaT = Numbers(7);
     928              : 
     929            1 :             if (lAlphaBlanks(5)) {
     930            0 :             } else if ((thisRadSysDesign.changeoverDelaySched = Sched::GetSchedule(state, Alphas(5))) == nullptr) {
     931            0 :                 ShowWarningItemNotFound(state, eoh, cAlphaFields(5), Alphas(5), "No changeover delay will be used for this radiant system.");
     932              :             }
     933            1 :             CFlowRadDesignNames(Item) = Alphas(1);
     934              :         }
     935              : 
     936              :         // Obtain all of the user data related to constant flow (hydronic) low temperature radiant systems...
     937            5 :         CurrentModuleObject = "ZoneHVAC:LowTemperatureRadiant:ConstantFlow";
     938            6 :         for (Item = 1; Item <= state.dataLowTempRadSys->NumOfCFloLowTempRadSys; ++Item) {
     939              : 
     940            1 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
     941              :                                                                      CurrentModuleObject,
     942              :                                                                      Item,
     943              :                                                                      Alphas,
     944              :                                                                      NumAlphas,
     945              :                                                                      Numbers,
     946              :                                                                      NumNumbers,
     947              :                                                                      IOStatus,
     948              :                                                                      lNumericBlanks,
     949              :                                                                      lAlphaBlanks,
     950              :                                                                      cAlphaFields,
     951              :                                                                      cNumericFields);
     952              : 
     953            1 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
     954              : 
     955            1 :             GlobalNames::VerifyUniqueInterObjectName(
     956            2 :                 state, state.dataLowTempRadSys->LowTempRadUniqueNames, Alphas(1), CurrentModuleObject, cAlphaFields(1), ErrorsFound);
     957            1 :             ++BaseNum;
     958            1 :             state.dataLowTempRadSys->RadSysTypes(BaseNum).Name = Alphas(1);
     959            1 :             state.dataLowTempRadSys->RadSysTypes(BaseNum).systemType = SystemType::ConstantFlow;
     960              : 
     961              :             // General user input data
     962            1 :             auto &thisCFloSys = state.dataLowTempRadSys->CFloRadSys(Item);
     963              : 
     964            1 :             thisCFloSys.Name = Alphas(1);
     965            1 :             thisCFloSys.designObjectName = Alphas(2);
     966            1 :             thisCFloSys.DesignObjectPtr = Util::FindItemInList(thisCFloSys.designObjectName, CFlowRadDesignNames);
     967              :             ConstantFlowRadDesignData ConstantFlowRadDesignDataObject{
     968            1 :                 state.dataLowTempRadSys->CflowRadiantSysDesign(thisCFloSys.DesignObjectPtr)}; // Contains the data for variable flow hydronic systems
     969              : 
     970            1 :             if (lAlphaBlanks(3)) {
     971            0 :                 thisCFloSys.availSched = Sched::GetScheduleAlwaysOn(state);
     972            1 :             } else if ((thisCFloSys.availSched = Sched::GetSchedule(state, Alphas(3))) == nullptr) {
     973            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(3), Alphas(3));
     974            0 :                 ErrorsFound = true;
     975              :             }
     976              : 
     977            1 :             thisCFloSys.ZoneName = Alphas(4);
     978            1 :             thisCFloSys.ZonePtr = Util::FindItemInList(Alphas(4), Zone);
     979            1 :             if (thisCFloSys.ZonePtr == 0) {
     980            0 :                 ShowSevereError(state, format("{}Invalid {} = {}", RoutineName, cAlphaFields(4), Alphas(4)));
     981            0 :                 ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, Alphas(1)));
     982            0 :                 ErrorsFound = true;
     983              :             }
     984              : 
     985            1 :             thisCFloSys.SurfListName = Alphas(5);
     986            1 :             SurfListNum = 0;
     987            1 :             if (state.dataSurfLists->NumOfSurfaceLists > 0)
     988            1 :                 SurfListNum = Util::FindItemInList(thisCFloSys.SurfListName, state.dataSurfLists->SurfList);
     989            1 :             if (SurfListNum > 0) { // Found a valid surface list
     990            1 :                 thisCFloSys.NumOfSurfaces = state.dataSurfLists->SurfList(SurfListNum).NumOfSurfaces;
     991            1 :                 thisCFloSys.SurfacePtr.allocate(thisCFloSys.NumOfSurfaces);
     992            1 :                 thisCFloSys.SurfaceName.allocate(thisCFloSys.NumOfSurfaces);
     993            1 :                 thisCFloSys.SurfaceFrac.allocate(thisCFloSys.NumOfSurfaces);
     994            1 :                 thisCFloSys.NumCircuits.allocate(thisCFloSys.NumOfSurfaces);
     995            1 :                 state.dataLowTempRadSys->MaxCloNumOfSurfaces = max(state.dataLowTempRadSys->MaxCloNumOfSurfaces, thisCFloSys.NumOfSurfaces);
     996            3 :                 for (SurfNum = 1; SurfNum <= state.dataSurfLists->SurfList(SurfListNum).NumOfSurfaces; ++SurfNum) {
     997            2 :                     thisCFloSys.SurfacePtr(SurfNum) = state.dataSurfLists->SurfList(SurfListNum).SurfPtr(SurfNum);
     998            2 :                     thisCFloSys.SurfaceName(SurfNum) = state.dataSurfLists->SurfList(SurfListNum).SurfName(SurfNum);
     999            2 :                     thisCFloSys.SurfaceFrac(SurfNum) = state.dataSurfLists->SurfList(SurfListNum).SurfFlowFrac(SurfNum);
    1000            2 :                     thisCFloSys.NumCircuits(SurfNum) = 0.0;
    1001            2 :                     if (thisCFloSys.SurfacePtr(SurfNum) != 0) {
    1002            2 :                         state.dataSurface->surfIntConv(thisCFloSys.SurfacePtr(SurfNum)).hasActiveInIt = true;
    1003              :                     }
    1004              :                 }
    1005              :             } else { // User entered a single surface name rather than a surface list
    1006            0 :                 thisCFloSys.NumOfSurfaces = 1;
    1007            0 :                 thisCFloSys.SurfacePtr.allocate(thisCFloSys.NumOfSurfaces);
    1008            0 :                 thisCFloSys.SurfaceName.allocate(thisCFloSys.NumOfSurfaces);
    1009            0 :                 thisCFloSys.SurfaceFrac.allocate(thisCFloSys.NumOfSurfaces);
    1010            0 :                 thisCFloSys.NumCircuits.allocate(thisCFloSys.NumOfSurfaces);
    1011            0 :                 state.dataLowTempRadSys->MaxCloNumOfSurfaces = max(state.dataLowTempRadSys->MaxCloNumOfSurfaces, thisCFloSys.NumOfSurfaces);
    1012            0 :                 thisCFloSys.SurfaceName(1) = thisCFloSys.SurfListName;
    1013            0 :                 thisCFloSys.SurfacePtr(1) = Util::FindItemInList(thisCFloSys.SurfaceName(1), Surface);
    1014            0 :                 thisCFloSys.SurfaceFrac(1) = 1.0;
    1015            0 :                 thisCFloSys.NumCircuits(1) = 0.0;
    1016              :                 // Error checking for single surfaces
    1017            0 :                 if (thisCFloSys.SurfacePtr(1) == 0) {
    1018            0 :                     ShowSevereError(state, format("{}Invalid {} = {}", RoutineName, cAlphaFields(4), Alphas(4)));
    1019            0 :                     ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1020            0 :                     ErrorsFound = true;
    1021            0 :                 } else if (state.dataSurface->SurfIsRadSurfOrVentSlabOrPool(thisCFloSys.SurfacePtr(1))) {
    1022            0 :                     ShowSevereError(state, format("{}{}=\"{}\", Invalid Surface", RoutineName, CurrentModuleObject, Alphas(1)));
    1023            0 :                     ShowContinueError(state,
    1024            0 :                                       format("{}=\"{}\" has been used in another radiant system or ventilated slab.", cAlphaFields(5), Alphas(5)));
    1025            0 :                     ErrorsFound = true;
    1026              :                 }
    1027            0 :                 if (thisCFloSys.SurfacePtr(1) != 0) {
    1028            0 :                     state.dataSurface->surfIntConv(thisCFloSys.SurfacePtr(1)).hasActiveInIt = true;
    1029            0 :                     state.dataSurface->SurfIsRadSurfOrVentSlabOrPool(thisCFloSys.SurfacePtr(1)) = true;
    1030              :                 }
    1031              :             }
    1032              : 
    1033              :             // Error checking for zones and construction information
    1034            1 :             thisCFloSys.errorCheckZonesAndConstructions(state, ErrorsFound);
    1035              : 
    1036            1 :             thisCFloSys.TubeLength = Numbers(1);
    1037              : 
    1038              :             // Process pump input for constant flow (hydronic) radiant system
    1039            1 :             thisCFloSys.WaterVolFlowMax = Numbers(2);
    1040              : 
    1041            1 :             if (lAlphaBlanks(6)) {
    1042            0 :             } else if ((thisCFloSys.volFlowSched = Sched::GetSchedule(state, Alphas(6))) == nullptr) {
    1043            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(6), Alphas(6));
    1044            0 :                 ErrorsFound = true;
    1045              :             }
    1046            1 :             thisCFloSys.NomPumpHead = Numbers(3);
    1047            1 :             thisCFloSys.NomPowerUse = Numbers(4);
    1048              : 
    1049              :             // Heating user input data
    1050            1 :             thisCFloSys.HotWaterInNode = GetOnlySingleNode(state,
    1051            1 :                                                            Alphas(7),
    1052              :                                                            ErrorsFound,
    1053              :                                                            DataLoopNode::ConnectionObjectType::ZoneHVACLowTemperatureRadiantConstantFlow,
    1054            1 :                                                            Alphas(1),
    1055              :                                                            DataLoopNode::NodeFluidType::Water,
    1056              :                                                            DataLoopNode::ConnectionType::Inlet,
    1057              :                                                            NodeInputManager::CompFluidStream::Primary,
    1058              :                                                            ObjectIsNotParent);
    1059              : 
    1060            1 :             thisCFloSys.HotWaterOutNode = GetOnlySingleNode(state,
    1061            1 :                                                             Alphas(8),
    1062              :                                                             ErrorsFound,
    1063              :                                                             DataLoopNode::ConnectionObjectType::ZoneHVACLowTemperatureRadiantConstantFlow,
    1064            1 :                                                             Alphas(1),
    1065              :                                                             DataLoopNode::NodeFluidType::Water,
    1066              :                                                             DataLoopNode::ConnectionType::Outlet,
    1067              :                                                             NodeInputManager::CompFluidStream::Primary,
    1068              :                                                             ObjectIsNotParent);
    1069              : 
    1070            1 :             if ((!lAlphaBlanks(7)) || (!lAlphaBlanks(8))) {
    1071            0 :                 TestCompSet(state, CurrentModuleObject, Alphas(1), Alphas(7), Alphas(8), "Hot Water Nodes");
    1072              :             }
    1073              : 
    1074            1 :             if (lAlphaBlanks(9)) {
    1075            1 :             } else if ((thisCFloSys.hotWaterHiTempSched = Sched::GetSchedule(state, Alphas(9))) == nullptr) {
    1076            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(9), Alphas(9));
    1077            0 :                 ErrorsFound = true;
    1078              :             }
    1079              : 
    1080            1 :             if (lAlphaBlanks(10)) {
    1081            1 :             } else if ((thisCFloSys.hotWaterLoTempSched = Sched::GetSchedule(state, Alphas(10))) == nullptr) {
    1082            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(10), Alphas(10));
    1083            0 :                 ErrorsFound = true;
    1084              :             }
    1085              : 
    1086              :             // This may look like a weird thing to do, but it's equivalent to a nested if and also uses less nesting
    1087            1 :             if (lAlphaBlanks(11)) {
    1088            1 :             } else if ((thisCFloSys.hotCtrlHiTempSched = Sched::GetSchedule(state, Alphas(11))) == nullptr) {
    1089            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(11), Alphas(11));
    1090            0 :                 ErrorsFound = true;
    1091              :             }
    1092              : 
    1093            1 :             if (lAlphaBlanks(12)) {
    1094            1 :             } else if ((thisCFloSys.hotCtrlLoTempSched = Sched::GetSchedule(state, Alphas(12))) == nullptr) {
    1095            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(12), Alphas(12));
    1096            0 :                 ErrorsFound = true;
    1097              :             }
    1098              : 
    1099              :             // Cooling user input data
    1100            1 :             thisCFloSys.ColdWaterInNode = GetOnlySingleNode(state,
    1101            1 :                                                             Alphas(13),
    1102              :                                                             ErrorsFound,
    1103              :                                                             DataLoopNode::ConnectionObjectType::ZoneHVACLowTemperatureRadiantConstantFlow,
    1104            1 :                                                             Alphas(1),
    1105              :                                                             DataLoopNode::NodeFluidType::Water,
    1106              :                                                             DataLoopNode::ConnectionType::Inlet,
    1107              :                                                             NodeInputManager::CompFluidStream::Secondary,
    1108              :                                                             ObjectIsNotParent);
    1109              : 
    1110            1 :             thisCFloSys.ColdWaterOutNode = GetOnlySingleNode(state,
    1111            1 :                                                              Alphas(14),
    1112              :                                                              ErrorsFound,
    1113              :                                                              DataLoopNode::ConnectionObjectType::ZoneHVACLowTemperatureRadiantConstantFlow,
    1114            1 :                                                              Alphas(1),
    1115              :                                                              DataLoopNode::NodeFluidType::Water,
    1116              :                                                              DataLoopNode::ConnectionType::Outlet,
    1117              :                                                              NodeInputManager::CompFluidStream::Secondary,
    1118              :                                                              ObjectIsNotParent);
    1119              : 
    1120            1 :             if ((!lAlphaBlanks(13)) || (!lAlphaBlanks(14))) {
    1121            0 :                 TestCompSet(state, CurrentModuleObject, Alphas(1), Alphas(13), Alphas(14), "Chilled Water Nodes");
    1122              :             }
    1123              : 
    1124            1 :             if (lAlphaBlanks(15)) {
    1125            1 :             } else if ((thisCFloSys.coldWaterHiTempSched = Sched::GetSchedule(state, Alphas(15))) == nullptr) {
    1126            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(15), Alphas(15));
    1127            0 :                 ErrorsFound = true;
    1128              :             }
    1129              : 
    1130            1 :             if (lAlphaBlanks(16)) {
    1131            1 :             } else if ((thisCFloSys.coldWaterLoTempSched = Sched::GetSchedule(state, Alphas(16))) == nullptr) {
    1132            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(16), Alphas(16));
    1133            0 :                 ErrorsFound = true;
    1134              :             }
    1135              : 
    1136            1 :             if (lAlphaBlanks(17)) {
    1137            1 :             } else if ((thisCFloSys.coldCtrlHiTempSched = Sched::GetSchedule(state, Alphas(17))) == nullptr) {
    1138            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(17), Alphas(17));
    1139            0 :                 ErrorsFound = true;
    1140              :             }
    1141              : 
    1142            1 :             if (lAlphaBlanks(18)) {
    1143            1 :             } else if ((thisCFloSys.coldCtrlLoTempSched = Sched::GetSchedule(state, Alphas(18))) == nullptr) {
    1144            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(18), Alphas(18));
    1145            0 :                 ErrorsFound = true;
    1146              :             }
    1147              : 
    1148            1 :             if (lAlphaBlanks(19)) {
    1149            0 :                 thisCFloSys.NumCircCalcMethod = CircuitCalc::OneCircuit;
    1150            1 :             } else if ((thisCFloSys.NumCircCalcMethod = static_cast<CircuitCalc>(getEnumValue(circuitCalcNamesUC, Alphas(19)))) ==
    1151              :                        CircuitCalc::Invalid) {
    1152            0 :                 ShowWarningInvalidKey(state, eoh, cAlphaFields(19), Alphas(19), "OnePerSurface");
    1153            0 :                 thisCFloSys.NumCircCalcMethod = CircuitCalc::OneCircuit;
    1154              :             }
    1155              : 
    1156            1 :             thisCFloSys.changeoverDelaySched = ConstantFlowRadDesignDataObject.changeoverDelaySched;
    1157              : 
    1158            1 :             thisCFloSys.CircLength = Numbers(5);
    1159            1 :         }
    1160              : 
    1161              :         // Obtain all of the user data related to electric low temperature radiant systems...
    1162            5 :         CurrentModuleObject = "ZoneHVAC:LowTemperatureRadiant:Electric";
    1163              : 
    1164            8 :         for (Item = 1; Item <= state.dataLowTempRadSys->NumOfElecLowTempRadSys; ++Item) {
    1165              : 
    1166            3 :             state.dataInputProcessing->inputProcessor->getObjectItem(state,
    1167              :                                                                      CurrentModuleObject,
    1168              :                                                                      Item,
    1169              :                                                                      Alphas,
    1170              :                                                                      NumAlphas,
    1171              :                                                                      Numbers,
    1172              :                                                                      NumNumbers,
    1173              :                                                                      IOStatus,
    1174              :                                                                      lNumericBlanks,
    1175              :                                                                      lAlphaBlanks,
    1176              :                                                                      cAlphaFields,
    1177              :                                                                      cNumericFields);
    1178              : 
    1179            3 :             ErrorObjectHeader eoh{routineName, CurrentModuleObject, Alphas(1)};
    1180              : 
    1181            3 :             state.dataLowTempRadSys->ElecRadSysNumericFields(Item).FieldNames.allocate(NumNumbers);
    1182            3 :             state.dataLowTempRadSys->ElecRadSysNumericFields(Item).FieldNames = "";
    1183            3 :             state.dataLowTempRadSys->ElecRadSysNumericFields(Item).FieldNames = cNumericFields;
    1184              : 
    1185            3 :             GlobalNames::VerifyUniqueInterObjectName(
    1186            6 :                 state, state.dataLowTempRadSys->LowTempRadUniqueNames, Alphas(1), CurrentModuleObject, cAlphaFields(1), ErrorsFound);
    1187            3 :             ++BaseNum;
    1188            3 :             state.dataLowTempRadSys->RadSysTypes(BaseNum).Name = Alphas(1);
    1189            3 :             state.dataLowTempRadSys->RadSysTypes(BaseNum).systemType = SystemType::Electric;
    1190              : 
    1191              :             // General user input data
    1192            3 :             auto &thisElecSys = state.dataLowTempRadSys->ElecRadSys(Item);
    1193              : 
    1194            3 :             thisElecSys.Name = Alphas(1);
    1195              : 
    1196            3 :             if (lAlphaBlanks(2)) {
    1197            0 :                 thisElecSys.availSched = Sched::GetScheduleAlwaysOn(state);
    1198            3 :             } else if ((thisElecSys.availSched = Sched::GetSchedule(state, Alphas(2))) == nullptr) {
    1199            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(2), Alphas(2));
    1200            0 :                 ErrorsFound = true;
    1201              :             }
    1202              : 
    1203            3 :             thisElecSys.ZoneName = Alphas(3);
    1204            3 :             thisElecSys.ZonePtr = Util::FindItemInList(Alphas(3), Zone);
    1205            3 :             if (thisElecSys.ZonePtr == 0) {
    1206            0 :                 ShowSevereError(state, format("{}Invalid {} = {}", RoutineName, cAlphaFields(3), Alphas(3)));
    1207            0 :                 ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1208            0 :                 ErrorsFound = true;
    1209              :             }
    1210              : 
    1211            3 :             thisElecSys.SurfListName = Alphas(4);
    1212            3 :             SurfListNum = 0;
    1213            3 :             if (state.dataSurfLists->NumOfSurfaceLists > 0)
    1214            3 :                 SurfListNum = Util::FindItemInList(thisElecSys.SurfListName, state.dataSurfLists->SurfList);
    1215            3 :             if (SurfListNum > 0) { // Found a valid surface list
    1216            3 :                 thisElecSys.NumOfSurfaces = state.dataSurfLists->SurfList(SurfListNum).NumOfSurfaces;
    1217            3 :                 thisElecSys.SurfacePtr.allocate(thisElecSys.NumOfSurfaces);
    1218            3 :                 thisElecSys.SurfaceName.allocate(thisElecSys.NumOfSurfaces);
    1219            3 :                 thisElecSys.SurfaceFrac.allocate(thisElecSys.NumOfSurfaces);
    1220            9 :                 for (SurfNum = 1; SurfNum <= state.dataSurfLists->SurfList(SurfListNum).NumOfSurfaces; ++SurfNum) {
    1221            6 :                     thisElecSys.SurfacePtr(SurfNum) = state.dataSurfLists->SurfList(SurfListNum).SurfPtr(SurfNum);
    1222            6 :                     thisElecSys.SurfaceName(SurfNum) = state.dataSurfLists->SurfList(SurfListNum).SurfName(SurfNum);
    1223            6 :                     thisElecSys.SurfaceFrac(SurfNum) = state.dataSurfLists->SurfList(SurfListNum).SurfFlowFrac(SurfNum);
    1224              :                 }
    1225              :             } else { // User entered a single surface name rather than a surface list
    1226            0 :                 thisElecSys.NumOfSurfaces = 1;
    1227            0 :                 thisElecSys.SurfacePtr.allocate(thisElecSys.NumOfSurfaces);
    1228            0 :                 thisElecSys.SurfaceName.allocate(thisElecSys.NumOfSurfaces);
    1229            0 :                 thisElecSys.SurfaceFrac.allocate(thisElecSys.NumOfSurfaces);
    1230            0 :                 thisElecSys.SurfaceName(1) = thisElecSys.SurfListName;
    1231            0 :                 thisElecSys.SurfacePtr(1) = Util::FindItemInList(thisElecSys.SurfaceName(1), Surface);
    1232            0 :                 thisElecSys.SurfaceFrac(1) = 1.0;
    1233              :                 // Error checking for single surfaces
    1234            0 :                 if (thisElecSys.SurfacePtr(1) == 0) {
    1235            0 :                     ShowSevereError(state, format("{}Invalid {} = {}", RoutineName, cAlphaFields(4), Alphas(4)));
    1236            0 :                     ShowContinueError(state, format("Occurs in {} = {}", CurrentModuleObject, Alphas(1)));
    1237            0 :                     ErrorsFound = true;
    1238            0 :                 } else if (state.dataSurface->SurfIsRadSurfOrVentSlabOrPool(thisElecSys.SurfacePtr(1))) {
    1239            0 :                     ShowSevereError(state, format("{}{}=\"{}\", Invalid Surface", RoutineName, CurrentModuleObject, Alphas(1)));
    1240            0 :                     ShowContinueError(state,
    1241            0 :                                       format("{}=\"{}\" has been used in another radiant system or ventilated slab.", cAlphaFields(4), Alphas(4)));
    1242            0 :                     ErrorsFound = true;
    1243              :                 }
    1244            0 :                 if (thisElecSys.SurfacePtr(1) != 0) {
    1245            0 :                     state.dataSurface->SurfIsRadSurfOrVentSlabOrPool(state.dataLowTempRadSys->ElecRadSys(Item).SurfacePtr(1)) = true;
    1246              :                 }
    1247              :             }
    1248              : 
    1249              :             // Error checking for zones and construction information
    1250            3 :             thisElecSys.errorCheckZonesAndConstructions(state, ErrorsFound);
    1251              : 
    1252              :             // Heating user input data
    1253              :             // Determine Low Temp Radiant heating design capacity sizing method
    1254            3 :             if (Util::SameString(Alphas(iHeatCAPMAlphaNum), "HeatingDesignCapacity")) {
    1255            3 :                 thisElecSys.HeatingCapMethod = HeatingDesignCapacity;
    1256            3 :                 if (!lNumericBlanks(iHeatDesignCapacityNumericNum)) {
    1257            3 :                     thisElecSys.ScaledHeatingCapacity = Numbers(iHeatDesignCapacityNumericNum);
    1258            3 :                     thisElecSys.MaxElecPower = thisElecSys.ScaledHeatingCapacity;
    1259            3 :                     if (thisElecSys.ScaledHeatingCapacity < 0.0 && thisElecSys.ScaledHeatingCapacity != AutoSize) {
    1260            0 :                         ShowSevereError(state, format("{} = {}", CurrentModuleObject, thisElecSys.Name));
    1261            0 :                         ShowContinueError(
    1262              :                             state,
    1263            0 :                             format("Illegal {} = {:.7T}", cNumericFields(iHeatDesignCapacityNumericNum), Numbers(iHeatDesignCapacityNumericNum)));
    1264            0 :                         ErrorsFound = true;
    1265              :                     }
    1266              :                 } else {
    1267            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, thisElecSys.Name));
    1268            0 :                     ShowContinueError(state, format("Input for {} = {}", cAlphaFields(iHeatCAPMAlphaNum), Alphas(iHeatCAPMAlphaNum)));
    1269            0 :                     ShowContinueError(state, format("Blank field not allowed for {}", cNumericFields(iHeatDesignCapacityNumericNum)));
    1270            0 :                     ErrorsFound = true;
    1271              :                 }
    1272            0 :             } else if (Util::SameString(Alphas(iHeatCAPMAlphaNum), "CapacityPerFloorArea")) {
    1273            0 :                 thisElecSys.HeatingCapMethod = CapacityPerFloorArea;
    1274            0 :                 if (!lNumericBlanks(iHeatCapacityPerFloorAreaNumericNum)) {
    1275            0 :                     thisElecSys.ScaledHeatingCapacity = Numbers(iHeatCapacityPerFloorAreaNumericNum);
    1276            0 :                     thisElecSys.MaxElecPower = thisElecSys.ScaledHeatingCapacity;
    1277            0 :                     if (thisElecSys.ScaledHeatingCapacity <= 0.0) {
    1278            0 :                         ShowSevereError(state, format("{} = {}", CurrentModuleObject, thisElecSys.Name));
    1279            0 :                         ShowContinueError(state, format("Input for {} = {}", cAlphaFields(iHeatCAPMAlphaNum), Alphas(iHeatCAPMAlphaNum)));
    1280            0 :                         ShowContinueError(state,
    1281            0 :                                           format("Illegal {} = {:.7T}",
    1282              :                                                  cNumericFields(iHeatCapacityPerFloorAreaNumericNum),
    1283              :                                                  Numbers(iHeatCapacityPerFloorAreaNumericNum)));
    1284            0 :                         ErrorsFound = true;
    1285            0 :                     } else if (thisElecSys.ScaledHeatingCapacity == AutoSize) {
    1286            0 :                         ShowSevereError(state, format("{} = {}", CurrentModuleObject, thisElecSys.Name));
    1287            0 :                         ShowContinueError(state, format("Input for {} = {}", cAlphaFields(iHeatCAPMAlphaNum), Alphas(iHeatCAPMAlphaNum)));
    1288            0 :                         ShowContinueError(state, format("Illegal {} = Autosize", cNumericFields(iHeatCapacityPerFloorAreaNumericNum)));
    1289            0 :                         ErrorsFound = true;
    1290              :                     }
    1291              :                 } else {
    1292            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, thisElecSys.Name));
    1293            0 :                     ShowContinueError(state, format("Input for {} = {}", cAlphaFields(iHeatCAPMAlphaNum), Alphas(iHeatCAPMAlphaNum)));
    1294            0 :                     ShowContinueError(state, format("Blank field not allowed for {}", cNumericFields(iHeatCapacityPerFloorAreaNumericNum)));
    1295            0 :                     ErrorsFound = true;
    1296              :                 }
    1297            0 :             } else if (Util::SameString(Alphas(iHeatCAPMAlphaNum), "FractionOfAutosizedHeatingCapacity")) {
    1298            0 :                 thisElecSys.HeatingCapMethod = FractionOfAutosizedHeatingCapacity;
    1299            0 :                 if (!lNumericBlanks(iHeatFracOfAutosizedCapacityNumericNum)) {
    1300            0 :                     thisElecSys.ScaledHeatingCapacity = Numbers(iHeatFracOfAutosizedCapacityNumericNum);
    1301            0 :                     thisElecSys.MaxElecPower = thisElecSys.ScaledHeatingCapacity;
    1302            0 :                     if (thisElecSys.ScaledHeatingCapacity < 0.0) {
    1303            0 :                         ShowSevereError(state, format("{} = {}", CurrentModuleObject, thisElecSys.Name));
    1304            0 :                         ShowContinueError(state,
    1305            0 :                                           format("Illegal {} = {:.7T}",
    1306              :                                                  cNumericFields(iHeatFracOfAutosizedCapacityNumericNum),
    1307              :                                                  Numbers(iHeatFracOfAutosizedCapacityNumericNum)));
    1308            0 :                         ErrorsFound = true;
    1309              :                     }
    1310              :                 } else {
    1311            0 :                     ShowSevereError(state, format("{} = {}", CurrentModuleObject, thisElecSys.Name));
    1312            0 :                     ShowContinueError(state, format("Input for {} = {}", cAlphaFields(iHeatCAPMAlphaNum), Alphas(iHeatCAPMAlphaNum)));
    1313            0 :                     ShowContinueError(state, format("Blank field not allowed for {}", cNumericFields(iHeatFracOfAutosizedCapacityNumericNum)));
    1314            0 :                     ErrorsFound = true;
    1315              :                 }
    1316              :             } else {
    1317            0 :                 ShowSevereError(state, format("{} = {}", CurrentModuleObject, thisElecSys.Name));
    1318            0 :                 ShowContinueError(state, format("Illegal {} = {}", cAlphaFields(iHeatCAPMAlphaNum), Alphas(iHeatCAPMAlphaNum)));
    1319            0 :                 ErrorsFound = true;
    1320              :             }
    1321              : 
    1322              :             // Process the temperature control type
    1323            3 :             if (lAlphaBlanks(6)) {
    1324            0 :                 thisElecSys.controlType = CtrlType::MAT;
    1325            3 :             } else if ((thisElecSys.controlType = static_cast<CtrlType>(getEnumValue(ctrlTypeNamesUC, Alphas(6)))) == CtrlType::Invalid) {
    1326            0 :                 ShowWarningInvalidKey(state, eoh, cAlphaFields(6), Alphas(6), "MeanAirTemperature");
    1327            0 :                 thisElecSys.controlType = CtrlType::MAT;
    1328              :             }
    1329              : 
    1330              :             // Process the setpoint type
    1331            3 :             if (lAlphaBlanks(7)) {
    1332            0 :                 thisElecSys.setpointType = SetpointType::HalfFlowPower;
    1333            3 :             } else if ((thisElecSys.setpointType = static_cast<SetpointType>(getEnumValue(setpointTypeNamesUC, Alphas(7)))) ==
    1334              :                        SetpointType::Invalid) {
    1335            0 :                 ShowWarningInvalidKey(state, eoh, cAlphaFields(7), Alphas(7), "HalfFlowPower");
    1336            0 :                 thisElecSys.setpointType = SetpointType::HalfFlowPower;
    1337              :             }
    1338              : 
    1339            3 :             thisElecSys.ThrottlRange = Numbers(4);
    1340              : 
    1341            3 :             if (lAlphaBlanks(8)) {
    1342            0 :                 ShowSevereEmptyField(state, eoh, cAlphaFields(8));
    1343            0 :                 ErrorsFound = true;
    1344            3 :             } else if ((thisElecSys.setptSched = Sched::GetSchedule(state, Alphas(8))) == nullptr) {
    1345            0 :                 ShowSevereItemNotFound(state, eoh, cAlphaFields(8), Alphas(8));
    1346            0 :                 ErrorsFound = true;
    1347              :             }
    1348              :         }
    1349              : 
    1350              :         // Check to see if any surface is included in more than one radiant system.  This is not allowed
    1351              :         // and thus indicative that there is an error in the input file.  This is to make sure that two
    1352              :         // different radiant systems are competing for the same surface.  Allowing this to happen would
    1353              :         // result in lost energy somewhere and the situation really is not physically possible anyway.
    1354            5 :         AssignedAsRadiantSurface.dimension(state.dataSurface->TotSurfaces, false);
    1355              : 
    1356            9 :         for (Item = 1; Item <= state.dataLowTempRadSys->NumOfHydrLowTempRadSys; ++Item) {
    1357            9 :             for (SurfNum = 1; SurfNum <= state.dataLowTempRadSys->HydrRadSys(Item).NumOfSurfaces; ++SurfNum) {
    1358            5 :                 CheckSurfNum = state.dataLowTempRadSys->HydrRadSys(Item).SurfacePtr(SurfNum);
    1359            5 :                 if (CheckSurfNum == 0) continue;
    1360            5 :                 if (AssignedAsRadiantSurface(CheckSurfNum)) {
    1361            0 :                     ShowSevereError(
    1362            0 :                         state, format("Surface {} is referenced by more than one radiant system--this is not allowed", Surface(CheckSurfNum).Name));
    1363            0 :                     ErrorsFound = true;
    1364              :                 } else {
    1365            5 :                     AssignedAsRadiantSurface(CheckSurfNum) = true;
    1366              :                 }
    1367              :                 // Also check the other side of interzone partitions
    1368            5 :                 if ((Surface(CheckSurfNum).ExtBoundCond > 0) && (Surface(CheckSurfNum).ExtBoundCond != CheckSurfNum)) {
    1369            0 :                     if (AssignedAsRadiantSurface(Surface(CheckSurfNum).ExtBoundCond)) {
    1370            0 :                         ShowSevereError(state,
    1371            0 :                                         format("Interzone surface {} is referenced by more than one radiant system--this is not allowed",
    1372            0 :                                                Surface(Surface(CheckSurfNum).ExtBoundCond).Name));
    1373            0 :                         ErrorsFound = true;
    1374              :                     } else {
    1375            0 :                         AssignedAsRadiantSurface(Surface(CheckSurfNum).ExtBoundCond) = true;
    1376              :                     }
    1377              :                 }
    1378              :             }
    1379              :         }
    1380              : 
    1381            6 :         for (Item = 1; Item <= state.dataLowTempRadSys->NumOfCFloLowTempRadSys; ++Item) {
    1382            3 :             for (SurfNum = 1; SurfNum <= state.dataLowTempRadSys->CFloRadSys(Item).NumOfSurfaces; ++SurfNum) {
    1383            2 :                 CheckSurfNum = state.dataLowTempRadSys->CFloRadSys(Item).SurfacePtr(SurfNum);
    1384            2 :                 if (CheckSurfNum == 0) continue;
    1385            2 :                 if (AssignedAsRadiantSurface(CheckSurfNum)) {
    1386            0 :                     ShowSevereError(
    1387            0 :                         state, format("Surface {} is referenced by more than one radiant system--this is not allowed", Surface(CheckSurfNum).Name));
    1388            0 :                     ErrorsFound = true;
    1389              :                 } else {
    1390            2 :                     AssignedAsRadiantSurface(CheckSurfNum) = true;
    1391              :                 }
    1392              :                 // Also check the other side of interzone partitions
    1393            2 :                 if ((Surface(CheckSurfNum).ExtBoundCond > 0) && (Surface(CheckSurfNum).ExtBoundCond != CheckSurfNum)) {
    1394            0 :                     if (AssignedAsRadiantSurface(Surface(CheckSurfNum).ExtBoundCond)) {
    1395            0 :                         ShowSevereError(state,
    1396            0 :                                         format("Interzone surface {} is referenced by more than one radiant system--this is not allowed",
    1397            0 :                                                Surface(Surface(CheckSurfNum).ExtBoundCond).Name));
    1398            0 :                         ErrorsFound = true;
    1399              :                     } else {
    1400            0 :                         AssignedAsRadiantSurface(Surface(CheckSurfNum).ExtBoundCond) = true;
    1401              :                     }
    1402              :                 }
    1403              :             }
    1404              :         }
    1405              : 
    1406            8 :         for (Item = 1; Item <= state.dataLowTempRadSys->NumOfElecLowTempRadSys; ++Item) {
    1407            9 :             for (SurfNum = 1; SurfNum <= state.dataLowTempRadSys->ElecRadSys(Item).NumOfSurfaces; ++SurfNum) {
    1408            6 :                 CheckSurfNum = state.dataLowTempRadSys->ElecRadSys(Item).SurfacePtr(SurfNum);
    1409            6 :                 if (CheckSurfNum == 0) continue;
    1410            6 :                 if (AssignedAsRadiantSurface(CheckSurfNum)) {
    1411            0 :                     ShowSevereError(
    1412            0 :                         state, format("Surface {} is referenced by more than one radiant system--this is not allowed", Surface(CheckSurfNum).Name));
    1413            0 :                     ErrorsFound = true;
    1414              :                 } else {
    1415            6 :                     AssignedAsRadiantSurface(CheckSurfNum) = true;
    1416              :                 }
    1417              :                 // Also check the other side of interzone partitions
    1418            6 :                 if ((Surface(CheckSurfNum).ExtBoundCond > 0) && (Surface(CheckSurfNum).ExtBoundCond != CheckSurfNum)) {
    1419            0 :                     if (AssignedAsRadiantSurface(Surface(CheckSurfNum).ExtBoundCond)) {
    1420            0 :                         ShowSevereError(state,
    1421            0 :                                         format("Interzone surface {} is referenced by more than one radiant system--this is not allowed",
    1422            0 :                                                Surface(Surface(CheckSurfNum).ExtBoundCond).Name));
    1423            0 :                         ErrorsFound = true;
    1424              :                     } else {
    1425            0 :                         AssignedAsRadiantSurface(Surface(CheckSurfNum).ExtBoundCond) = true;
    1426              :                     }
    1427              :                 }
    1428              :             }
    1429              :         }
    1430              : 
    1431            5 :         AssignedAsRadiantSurface.deallocate();
    1432            5 :         Alphas.deallocate();
    1433            5 :         Numbers.deallocate();
    1434            5 :         cAlphaFields.deallocate();
    1435            5 :         cNumericFields.deallocate();
    1436            5 :         lAlphaBlanks.deallocate();
    1437            5 :         lNumericBlanks.deallocate();
    1438              : 
    1439            5 :         if (ErrorsFound) {
    1440            2 :             ShowFatalError(state, format("{}Errors found in input. Preceding conditions cause termination.", RoutineName));
    1441              :         }
    1442              : 
    1443              :         // Set up the output variables for low temperature radiant systems
    1444              :         // ZoneHVAC:LowTemperatureRadiant:VariableFlow (HydrRadSys)
    1445            7 :         for (Item = 1; Item <= state.dataLowTempRadSys->NumOfHydrLowTempRadSys; ++Item) {
    1446              : 
    1447            3 :             auto &thisHydrSys = state.dataLowTempRadSys->HydrRadSys(Item);
    1448              : 
    1449            6 :             SetupOutputVariable(state,
    1450              :                                 "Zone Radiant HVAC Heating Rate",
    1451              :                                 Constant::Units::W,
    1452            3 :                                 thisHydrSys.HeatPower,
    1453              :                                 OutputProcessor::TimeStepType::System,
    1454              :                                 OutputProcessor::StoreType::Average,
    1455            3 :                                 thisHydrSys.Name);
    1456            6 :             SetupOutputVariable(state,
    1457              :                                 "Zone Radiant HVAC Heating Energy",
    1458              :                                 Constant::Units::J,
    1459            3 :                                 thisHydrSys.HeatEnergy,
    1460              :                                 OutputProcessor::TimeStepType::System,
    1461              :                                 OutputProcessor::StoreType::Sum,
    1462            3 :                                 thisHydrSys.Name,
    1463              :                                 Constant::eResource::EnergyTransfer,
    1464              :                                 OutputProcessor::Group::HVAC,
    1465              :                                 OutputProcessor::EndUseCat::HeatingCoils);
    1466            6 :             SetupOutputVariable(state,
    1467              :                                 "Zone Radiant HVAC Heating Fluid Energy",
    1468              :                                 Constant::Units::J,
    1469            3 :                                 thisHydrSys.HeatEnergy,
    1470              :                                 OutputProcessor::TimeStepType::System,
    1471              :                                 OutputProcessor::StoreType::Sum,
    1472            3 :                                 thisHydrSys.Name,
    1473              :                                 Constant::eResource::PlantLoopHeatingDemand,
    1474              :                                 OutputProcessor::Group::HVAC,
    1475              :                                 OutputProcessor::EndUseCat::HeatingCoils);
    1476            6 :             SetupOutputVariable(state,
    1477              :                                 "Zone Radiant HVAC Cooling Rate",
    1478              :                                 Constant::Units::W,
    1479            3 :                                 thisHydrSys.CoolPower,
    1480              :                                 OutputProcessor::TimeStepType::System,
    1481              :                                 OutputProcessor::StoreType::Average,
    1482            3 :                                 thisHydrSys.Name);
    1483              : 
    1484            6 :             SetupOutputVariable(state,
    1485              :                                 "Zone Radiant HVAC Cooling Energy",
    1486              :                                 Constant::Units::J,
    1487            3 :                                 thisHydrSys.CoolEnergy,
    1488              :                                 OutputProcessor::TimeStepType::System,
    1489              :                                 OutputProcessor::StoreType::Sum,
    1490            3 :                                 thisHydrSys.Name,
    1491              :                                 Constant::eResource::EnergyTransfer,
    1492              :                                 OutputProcessor::Group::HVAC,
    1493              :                                 OutputProcessor::EndUseCat::CoolingCoils);
    1494            6 :             SetupOutputVariable(state,
    1495              :                                 "Zone Radiant HVAC Cooling Fluid Energy",
    1496              :                                 Constant::Units::J,
    1497            3 :                                 thisHydrSys.CoolEnergy,
    1498              :                                 OutputProcessor::TimeStepType::System,
    1499              :                                 OutputProcessor::StoreType::Sum,
    1500            3 :                                 thisHydrSys.Name,
    1501              :                                 Constant::eResource::PlantLoopCoolingDemand,
    1502              :                                 OutputProcessor::Group::HVAC,
    1503              :                                 OutputProcessor::EndUseCat::CoolingCoils);
    1504            6 :             SetupOutputVariable(state,
    1505              :                                 "Zone Radiant HVAC Mass Flow Rate",
    1506              :                                 Constant::Units::kg_s,
    1507            3 :                                 thisHydrSys.WaterMassFlowRate,
    1508              :                                 OutputProcessor::TimeStepType::System,
    1509              :                                 OutputProcessor::StoreType::Average,
    1510            3 :                                 thisHydrSys.Name);
    1511            6 :             SetupOutputVariable(state,
    1512              :                                 "Zone Radiant HVAC Inlet Temperature",
    1513              :                                 Constant::Units::C,
    1514            3 :                                 thisHydrSys.WaterInletTemp,
    1515              :                                 OutputProcessor::TimeStepType::System,
    1516              :                                 OutputProcessor::StoreType::Average,
    1517            3 :                                 thisHydrSys.Name);
    1518            6 :             SetupOutputVariable(state,
    1519              :                                 "Zone Radiant HVAC Outlet Temperature",
    1520              :                                 Constant::Units::C,
    1521            3 :                                 thisHydrSys.WaterOutletTemp,
    1522              :                                 OutputProcessor::TimeStepType::System,
    1523              :                                 OutputProcessor::StoreType::Average,
    1524            3 :                                 thisHydrSys.Name);
    1525            6 :             SetupOutputVariable(state,
    1526              :                                 "Zone Radiant HVAC Moisture Condensation Time",
    1527              :                                 Constant::Units::s,
    1528            3 :                                 thisHydrSys.CondCausedTimeOff,
    1529              :                                 OutputProcessor::TimeStepType::System,
    1530              :                                 OutputProcessor::StoreType::Sum,
    1531            3 :                                 thisHydrSys.Name);
    1532            3 :             SetupOutputVariable(state,
    1533              :                                 "Zone Radiant HVAC Operation Mode",
    1534              :                                 Constant::Units::None,
    1535            3 :                                 (int &)thisHydrSys.opMode,
    1536              :                                 OutputProcessor::TimeStepType::System,
    1537              :                                 OutputProcessor::StoreType::Average,
    1538            3 :                                 thisHydrSys.Name);
    1539            3 :             if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
    1540            0 :                 SetupEMSInternalVariable(state,
    1541              :                                          "Hydronic Low Temp Radiant Design Water Volume Flow Rate for Heating",
    1542              :                                          thisHydrSys.Name,
    1543              :                                          "[m3/s]",
    1544            0 :                                          thisHydrSys.WaterVolFlowMaxHeat);
    1545            0 :                 SetupEMSInternalVariable(state,
    1546              :                                          "Hydronic Low Temp Radiant Design Water Volume Flow Rate for Cooling",
    1547              :                                          thisHydrSys.Name,
    1548              :                                          "[m3/s]",
    1549            0 :                                          thisHydrSys.WaterVolFlowMaxCool);
    1550            0 :                 SetupEMSActuator(state,
    1551              :                                  "Hydronic Low Temp Radiant",
    1552              :                                  thisHydrSys.Name,
    1553              :                                  "Water Mass Flow Rate",
    1554              :                                  "[kg/s]",
    1555            0 :                                  thisHydrSys.EMSOverrideOnWaterMdot,
    1556            0 :                                  thisHydrSys.EMSWaterMdotOverrideValue);
    1557              :             }
    1558              :         }
    1559              : 
    1560              :         // Set up the output variables for low temperature radiant systems
    1561              :         // ZoneHVAC:LowTemperatureRadiant:ConstantFlow (CFloRadSys)
    1562            5 :         for (Item = 1; Item <= state.dataLowTempRadSys->NumOfCFloLowTempRadSys; ++Item) {
    1563              : 
    1564            1 :             auto &thisCFloSys = state.dataLowTempRadSys->CFloRadSys(Item);
    1565              : 
    1566            2 :             SetupOutputVariable(state,
    1567              :                                 "Zone Radiant HVAC Heating Rate",
    1568              :                                 Constant::Units::W,
    1569            1 :                                 thisCFloSys.HeatPower,
    1570              :                                 OutputProcessor::TimeStepType::System,
    1571              :                                 OutputProcessor::StoreType::Average,
    1572            1 :                                 thisCFloSys.Name);
    1573            2 :             SetupOutputVariable(state,
    1574              :                                 "Zone Radiant HVAC Heating Energy",
    1575              :                                 Constant::Units::J,
    1576            1 :                                 thisCFloSys.HeatEnergy,
    1577              :                                 OutputProcessor::TimeStepType::System,
    1578              :                                 OutputProcessor::StoreType::Sum,
    1579            1 :                                 thisCFloSys.Name,
    1580              :                                 Constant::eResource::EnergyTransfer,
    1581              :                                 OutputProcessor::Group::HVAC,
    1582              :                                 OutputProcessor::EndUseCat::HeatingCoils);
    1583            2 :             SetupOutputVariable(state,
    1584              :                                 "Zone Radiant HVAC Heating Fluid Heat Transfer Energy",
    1585              :                                 Constant::Units::J,
    1586            1 :                                 thisCFloSys.HeatEnergy,
    1587              :                                 OutputProcessor::TimeStepType::System,
    1588              :                                 OutputProcessor::StoreType::Sum,
    1589            1 :                                 thisCFloSys.Name,
    1590              :                                 Constant::eResource::PlantLoopHeatingDemand,
    1591              :                                 OutputProcessor::Group::HVAC,
    1592              :                                 OutputProcessor::EndUseCat::HeatingCoils);
    1593            2 :             SetupOutputVariable(state,
    1594              :                                 "Zone Radiant HVAC Cooling Rate",
    1595              :                                 Constant::Units::W,
    1596            1 :                                 thisCFloSys.CoolPower,
    1597              :                                 OutputProcessor::TimeStepType::System,
    1598              :                                 OutputProcessor::StoreType::Average,
    1599            1 :                                 thisCFloSys.Name);
    1600            2 :             SetupOutputVariable(state,
    1601              :                                 "Zone Radiant HVAC Cooling Energy",
    1602              :                                 Constant::Units::J,
    1603            1 :                                 thisCFloSys.CoolEnergy,
    1604              :                                 OutputProcessor::TimeStepType::System,
    1605              :                                 OutputProcessor::StoreType::Sum,
    1606            1 :                                 thisCFloSys.Name,
    1607              :                                 Constant::eResource::EnergyTransfer,
    1608              :                                 OutputProcessor::Group::HVAC,
    1609              :                                 OutputProcessor::EndUseCat::CoolingCoils);
    1610            2 :             SetupOutputVariable(state,
    1611              :                                 "Zone Radiant HVAC Cooling Fluid Heat Transfer Energy",
    1612              :                                 Constant::Units::J,
    1613            1 :                                 thisCFloSys.CoolEnergy,
    1614              :                                 OutputProcessor::TimeStepType::System,
    1615              :                                 OutputProcessor::StoreType::Sum,
    1616            1 :                                 thisCFloSys.Name,
    1617              :                                 Constant::eResource::PlantLoopCoolingDemand,
    1618              :                                 OutputProcessor::Group::HVAC,
    1619              :                                 OutputProcessor::EndUseCat::CoolingCoils);
    1620            2 :             SetupOutputVariable(state,
    1621              :                                 "Zone Radiant HVAC Mass Flow Rate",
    1622              :                                 Constant::Units::kg_s,
    1623            1 :                                 thisCFloSys.WaterMassFlowRate,
    1624              :                                 OutputProcessor::TimeStepType::System,
    1625              :                                 OutputProcessor::StoreType::Average,
    1626            1 :                                 thisCFloSys.Name);
    1627            2 :             SetupOutputVariable(state,
    1628              :                                 "Zone Radiant HVAC Injection Mass Flow Rate",
    1629              :                                 Constant::Units::kg_s,
    1630            1 :                                 thisCFloSys.WaterInjectionRate,
    1631              :                                 OutputProcessor::TimeStepType::System,
    1632              :                                 OutputProcessor::StoreType::Average,
    1633            1 :                                 thisCFloSys.Name);
    1634            2 :             SetupOutputVariable(state,
    1635              :                                 "Zone Radiant HVAC Recirculation Mass Flow Rate",
    1636              :                                 Constant::Units::kg_s,
    1637            1 :                                 thisCFloSys.WaterRecircRate,
    1638              :                                 OutputProcessor::TimeStepType::System,
    1639              :                                 OutputProcessor::StoreType::Average,
    1640            1 :                                 thisCFloSys.Name);
    1641            2 :             SetupOutputVariable(state,
    1642              :                                 "Zone Radiant HVAC Inlet Temperature",
    1643              :                                 Constant::Units::C,
    1644            1 :                                 thisCFloSys.WaterInletTemp,
    1645              :                                 OutputProcessor::TimeStepType::System,
    1646              :                                 OutputProcessor::StoreType::Average,
    1647            1 :                                 thisCFloSys.Name);
    1648            2 :             SetupOutputVariable(state,
    1649              :                                 "Zone Radiant HVAC Outlet Temperature",
    1650              :                                 Constant::Units::C,
    1651            1 :                                 thisCFloSys.WaterOutletTemp,
    1652              :                                 OutputProcessor::TimeStepType::System,
    1653              :                                 OutputProcessor::StoreType::Average,
    1654            1 :                                 thisCFloSys.Name);
    1655            2 :             SetupOutputVariable(state,
    1656              :                                 "Zone Radiant HVAC Pump Inlet Temperature",
    1657              :                                 Constant::Units::C,
    1658            1 :                                 thisCFloSys.PumpInletTemp,
    1659              :                                 OutputProcessor::TimeStepType::System,
    1660              :                                 OutputProcessor::StoreType::Average,
    1661            1 :                                 thisCFloSys.Name);
    1662            2 :             SetupOutputVariable(state,
    1663              :                                 "Zone Radiant HVAC Pump Electricity Rate",
    1664              :                                 Constant::Units::W,
    1665            1 :                                 thisCFloSys.PumpPower,
    1666              :                                 OutputProcessor::TimeStepType::System,
    1667              :                                 OutputProcessor::StoreType::Average,
    1668            1 :                                 thisCFloSys.Name);
    1669            2 :             SetupOutputVariable(state,
    1670              :                                 "Zone Radiant HVAC Pump Electricity Energy",
    1671              :                                 Constant::Units::J,
    1672            1 :                                 thisCFloSys.PumpEnergy,
    1673              :                                 OutputProcessor::TimeStepType::System,
    1674              :                                 OutputProcessor::StoreType::Sum,
    1675            1 :                                 thisCFloSys.Name,
    1676              :                                 Constant::eResource::Electricity,
    1677              :                                 OutputProcessor::Group::Plant,
    1678              :                                 OutputProcessor::EndUseCat::Pumps);
    1679            2 :             SetupOutputVariable(state,
    1680              :                                 "Zone Radiant HVAC Pump Mass Flow Rate",
    1681              :                                 Constant::Units::kg_s,
    1682            1 :                                 thisCFloSys.PumpMassFlowRate,
    1683              :                                 OutputProcessor::TimeStepType::System,
    1684              :                                 OutputProcessor::StoreType::Average,
    1685            1 :                                 thisCFloSys.Name);
    1686            2 :             SetupOutputVariable(state,
    1687              :                                 "Zone Radiant HVAC Pump Fluid Heat Gain Rate",
    1688              :                                 Constant::Units::W,
    1689            1 :                                 thisCFloSys.PumpHeattoFluid,
    1690              :                                 OutputProcessor::TimeStepType::System,
    1691              :                                 OutputProcessor::StoreType::Average,
    1692            1 :                                 thisCFloSys.Name);
    1693            2 :             SetupOutputVariable(state,
    1694              :                                 "Zone Radiant HVAC Pump Fluid Heat Gain Energy",
    1695              :                                 Constant::Units::J,
    1696            1 :                                 thisCFloSys.PumpHeattoFluidEnergy,
    1697              :                                 OutputProcessor::TimeStepType::System,
    1698              :                                 OutputProcessor::StoreType::Sum,
    1699            1 :                                 thisCFloSys.Name);
    1700            2 :             SetupOutputVariable(state,
    1701              :                                 "Zone Radiant HVAC Moisture Condensation Time",
    1702              :                                 Constant::Units::s,
    1703            1 :                                 thisCFloSys.CondCausedTimeOff,
    1704              :                                 OutputProcessor::TimeStepType::System,
    1705              :                                 OutputProcessor::StoreType::Sum,
    1706            1 :                                 thisCFloSys.Name);
    1707            1 :             SetupOutputVariable(state,
    1708              :                                 "Zone Radiant HVAC Operation Mode",
    1709              :                                 Constant::Units::None,
    1710            1 :                                 (int &)thisCFloSys.opMode,
    1711              :                                 OutputProcessor::TimeStepType::System,
    1712              :                                 OutputProcessor::StoreType::Average,
    1713            1 :                                 thisCFloSys.Name);
    1714            1 :             if (state.dataLowTempRadSys->anyRadiantSystemUsingRunningMeanAverage) {
    1715            0 :                 SetupOutputVariable(state,
    1716              :                                     "Zone Radiant HVAC Running Mean Outdoor Dry-Bulb Temperature",
    1717              :                                     Constant::Units::C,
    1718            0 :                                     thisCFloSys.todayRunningMeanOutdoorDryBulbTemperature,
    1719              :                                     OutputProcessor::TimeStepType::System,
    1720              :                                     OutputProcessor::StoreType::Average,
    1721            0 :                                     thisCFloSys.Name);
    1722            0 :                 SetupOutputVariable(state,
    1723              :                                     "Zone Radiant HVAC Previous Day Running Mean Outdoor Dry-Bulb Temperature",
    1724              :                                     Constant::Units::C,
    1725            0 :                                     thisCFloSys.yesterdayRunningMeanOutdoorDryBulbTemperature,
    1726              :                                     OutputProcessor::TimeStepType::System,
    1727              :                                     OutputProcessor::StoreType::Average,
    1728            0 :                                     thisCFloSys.Name);
    1729            0 :                 SetupOutputVariable(state,
    1730              :                                     "Zone Radiant HVAC Previous Day Average Outdoor Dry-Bulb Temperature",
    1731              :                                     Constant::Units::C,
    1732            0 :                                     thisCFloSys.yesterdayAverageOutdoorDryBulbTemperature,
    1733              :                                     OutputProcessor::TimeStepType::System,
    1734              :                                     OutputProcessor::StoreType::Average,
    1735            0 :                                     thisCFloSys.Name);
    1736              :             }
    1737            1 :             if (state.dataGlobal->AnyEnergyManagementSystemInModel) {
    1738            0 :                 SetupEMSInternalVariable(
    1739            0 :                     state, "Constant Flow Low Temp Radiant Design Water Mass Flow Rate", thisCFloSys.Name, "[m3/s]", thisCFloSys.WaterVolFlowMax);
    1740            0 :                 SetupEMSActuator(state,
    1741              :                                  "Constant Flow Low Temp Radiant",
    1742              :                                  thisCFloSys.Name,
    1743              :                                  "Water Mass Flow Rate",
    1744              :                                  "[kg/s]",
    1745            0 :                                  thisCFloSys.EMSOverrideOnWaterMdot,
    1746            0 :                                  thisCFloSys.EMSWaterMdotOverrideValue);
    1747              :             }
    1748              :         }
    1749              : 
    1750            7 :         for (Item = 1; Item <= state.dataLowTempRadSys->NumOfElecLowTempRadSys; ++Item) {
    1751              :             // Set up the output variables for low temperature radiant systems
    1752              :             // ZoneHVAC:LowTemperatureRadiant:Electric (ElecRadSys)
    1753              : 
    1754            3 :             auto &thisElecSys = state.dataLowTempRadSys->ElecRadSys(Item);
    1755              : 
    1756            6 :             SetupOutputVariable(state,
    1757              :                                 "Zone Radiant HVAC Electricity Rate",
    1758              :                                 Constant::Units::W,
    1759            3 :                                 thisElecSys.ElecPower,
    1760              :                                 OutputProcessor::TimeStepType::System,
    1761              :                                 OutputProcessor::StoreType::Average,
    1762            3 :                                 thisElecSys.Name);
    1763            6 :             SetupOutputVariable(state,
    1764              :                                 "Zone Radiant HVAC Electricity Energy",
    1765              :                                 Constant::Units::J,
    1766            3 :                                 thisElecSys.ElecEnergy,
    1767              :                                 OutputProcessor::TimeStepType::System,
    1768              :                                 OutputProcessor::StoreType::Sum,
    1769            3 :                                 thisElecSys.Name,
    1770              :                                 Constant::eResource::Electricity,
    1771              :                                 OutputProcessor::Group::HVAC,
    1772              :                                 OutputProcessor::EndUseCat::Heating);
    1773            6 :             SetupOutputVariable(state,
    1774              :                                 "Zone Radiant HVAC Heating Rate",
    1775              :                                 Constant::Units::W,
    1776            3 :                                 thisElecSys.HeatPower,
    1777              :                                 OutputProcessor::TimeStepType::System,
    1778              :                                 OutputProcessor::StoreType::Average,
    1779            3 :                                 thisElecSys.Name);
    1780            6 :             SetupOutputVariable(state,
    1781              :                                 "Zone Radiant HVAC Heating Energy",
    1782              :                                 Constant::Units::J,
    1783            3 :                                 thisElecSys.HeatEnergy,
    1784              :                                 OutputProcessor::TimeStepType::System,
    1785              :                                 OutputProcessor::StoreType::Sum,
    1786            3 :                                 thisElecSys.Name,
    1787              :                                 Constant::eResource::EnergyTransfer,
    1788              :                                 OutputProcessor::Group::HVAC,
    1789              :                                 OutputProcessor::EndUseCat::HeatingCoils);
    1790              :         }
    1791           14 :     }
    1792              : 
    1793           12 :     void RadiantSystemBaseData::errorCheckZonesAndConstructions(EnergyPlusData &state, bool &errorsFound)
    1794              :     {
    1795           12 :         auto &Zone = state.dataHeatBal->Zone;
    1796           12 :         auto &Surface = state.dataSurface->Surface;
    1797              : 
    1798           12 :         Real64 zoneMultipliers = 0.0;
    1799           12 :         Real64 zoneMultipliersSurface = 0.0;
    1800           12 :         Real64 zoneMultiplersTolerance = 0.001;
    1801           37 :         for (int SurfNum = 1; SurfNum <= this->NumOfSurfaces; ++SurfNum) {
    1802              : 
    1803           25 :             if (this->SurfacePtr(SurfNum) == 0) continue; // invalid surface -- detected earlier
    1804              : 
    1805           25 :             if (state.dataGlobal->DisplayExtraWarnings) {
    1806              :                 // check zone numbers--ok if they are not the same
    1807              :                 // group warning issued earlier, show detailed warning here
    1808            0 :                 if (Surface(this->SurfacePtr(SurfNum)).Zone != this->ZonePtr) {
    1809            0 :                     ShowWarningError(state,
    1810              :                                      "A surface referenced in a Low Temperature Radiant System is not in same zone as the radiant system itself");
    1811            0 :                     ShowContinueError(state, format("Surface = {}", Surface(this->SurfacePtr(SurfNum)).Name));
    1812            0 :                     ShowContinueError(state,
    1813            0 :                                       format("Surface in Zone = {}. Radiant System in Zone = {}",
    1814            0 :                                              Zone(Surface(this->SurfacePtr(SurfNum)).Zone).Name,
    1815            0 :                                              this->ZoneName));
    1816            0 :                     ShowContinueError(state, format("Occurs in Low Temperature Radiant System = {}", this->Name));
    1817            0 :                     ShowContinueError(state, "If this is intentionally a radiant system with surfaces in more than one thermal zone,");
    1818            0 :                     ShowContinueError(state, "then ignore this warning message.  Otherwise, check the surfaces in this radiant system.");
    1819              :                 }
    1820              :             }
    1821              : 
    1822              :             // check zone multipliers--these must be the same
    1823           25 :             if (SurfNum == 1) zoneMultipliers = double(Zone(this->ZonePtr).Multiplier) * double(Zone(this->ZonePtr).ListMultiplier);
    1824           25 :             zoneMultipliersSurface = double(Zone(Surface(this->SurfacePtr(SurfNum)).Zone).Multiplier) *
    1825           25 :                                      double(Zone(Surface(this->SurfacePtr(SurfNum)).Zone).ListMultiplier);
    1826           25 :             if (std::abs(zoneMultipliers - zoneMultipliersSurface) > zoneMultiplersTolerance) {
    1827            2 :                 ShowSevereError(state, "The zone multipliers are not the same for all surfaces contained in this radiant system");
    1828            2 :                 ShowContinueError(state, "This is not allowed and must be fixed for the simulation to run.");
    1829            1 :                 ShowContinueError(state, format("Occurs in Low Temperature Radiant System = {}", this->Name));
    1830            1 :                 errorsFound = true;
    1831              :             }
    1832              : 
    1833              :             // make sure that this construction is defined with a source/sink--this must be the case or it can't serve as a radiant system surface
    1834           25 :             if (!state.dataConstruction->Construct(Surface(this->SurfacePtr(SurfNum)).Construction).SourceSinkPresent) {
    1835            2 :                 ShowSevereError(state, "Construction referenced in Radiant System Surface does not have a source/sink present");
    1836            2 :                 ShowContinueError(state,
    1837            2 :                                   format("Surface name= {}  Construction name = {}",
    1838            1 :                                          Surface(this->SurfacePtr(SurfNum)).Name,
    1839            1 :                                          state.dataConstruction->Construct(Surface(this->SurfacePtr(SurfNum)).Construction).Name));
    1840            2 :                 ShowContinueError(state, "Construction needs to be referenced by a \"ConstructionProperty:InternalHeatSource\" object.");
    1841            1 :                 errorsFound = true;
    1842              :             }
    1843              :         }
    1844           12 :     }
    1845              : 
    1846            6 :     void InitLowTempRadiantSystem(EnergyPlusData &state,
    1847              :                                   bool const FirstHVACIteration, // TRUE if 1st HVAC simulation of system timestep
    1848              :                                   int const RadSysNum, // Index for the low temperature radiant system under consideration within the derived types
    1849              :                                   SystemType const systemType, // Type of radiant system: hydronic, constant flow, or electric
    1850              :                                   bool &InitErrorsFound)
    1851              :     {
    1852              : 
    1853              :         // SUBROUTINE INFORMATION:
    1854              :         //       AUTHOR         Rick Strand
    1855              :         //       DATE WRITTEN   November 2000
    1856              : 
    1857              :         // Using/Aliasing
    1858              : 
    1859              :         using DataSizing::AutoSize;
    1860              :         using DataZoneEquipment::CheckZoneEquipmentList;
    1861              : 
    1862              :         using PlantUtilities::InitComponentNodes;
    1863              :         using PlantUtilities::ScanPlantLoopsForObject;
    1864              :         using PlantUtilities::SetComponentFlowRate;
    1865              : 
    1866              :         // SUBROUTINE PARAMETER DEFINITIONS:
    1867            6 :         Real64 constexpr ZeroTol(0.0000001); // Smallest non-zero value allowed
    1868            6 :         constexpr std::string_view RoutineName("InitLowTempRadiantSystem");
    1869              : 
    1870              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1871              :         Real64 CurrentFlowSchedule; // Schedule value for flow fraction in a constant flow radiant system
    1872              :         Real64 TotalEffic;          // Intermediate calculation variable for total pump efficiency
    1873              :         Real64 mdot;                // local fluid mass flow rate
    1874              :         Real64 rho;                 // local fluid density
    1875              :         bool errFlag;
    1876              : 
    1877            6 :         InitErrorsFound = false;
    1878              : 
    1879            6 :         auto const &Surface = state.dataSurface->Surface;
    1880              : 
    1881            6 :         if (state.dataLowTempRadSys->MyOneTimeFlag) {
    1882            5 :             state.dataLowTempRadSys->MyEnvrnFlagHydr.allocate(state.dataLowTempRadSys->NumOfHydrLowTempRadSys);
    1883            5 :             state.dataLowTempRadSys->MyEnvrnFlagCFlo.allocate(state.dataLowTempRadSys->NumOfCFloLowTempRadSys);
    1884            5 :             state.dataLowTempRadSys->MyEnvrnFlagElec.allocate(state.dataLowTempRadSys->NumOfElecLowTempRadSys);
    1885            5 :             state.dataLowTempRadSys->MyPlantScanFlagHydr.allocate(state.dataLowTempRadSys->NumOfHydrLowTempRadSys);
    1886            5 :             state.dataLowTempRadSys->MyPlantScanFlagCFlo.allocate(state.dataLowTempRadSys->NumOfCFloLowTempRadSys);
    1887            5 :             state.dataLowTempRadSys->MyPlantScanFlagHydr = true;
    1888            5 :             state.dataLowTempRadSys->MyPlantScanFlagCFlo = true;
    1889            5 :             state.dataLowTempRadSys->MyEnvrnFlagHydr = true;
    1890            5 :             state.dataLowTempRadSys->MyEnvrnFlagCFlo = true;
    1891            5 :             state.dataLowTempRadSys->MyEnvrnFlagElec = true;
    1892            5 :             state.dataLowTempRadSys->MyOneTimeFlag = false;
    1893              :         }
    1894              : 
    1895            6 :         if (state.dataLowTempRadSys->FirstTimeInit) {
    1896              : 
    1897            6 :             for (auto &thisLTRSys : state.dataLowTempRadSys->HydrRadSys) {
    1898            1 :                 thisLTRSys.QRadSysSrcAvg.dimension(thisLTRSys.NumOfSurfaces, 0.0);
    1899            1 :                 thisLTRSys.LastQRadSysSrc.dimension(thisLTRSys.NumOfSurfaces, 0.0);
    1900            1 :                 thisLTRSys.LastSysTimeElapsed = 0.0;
    1901            1 :                 thisLTRSys.LastTimeStepSys = 0.0;
    1902              :             }
    1903           10 :             for (auto &thisCFLTRSys : state.dataLowTempRadSys->CFloRadSys) {
    1904            5 :                 thisCFLTRSys.QRadSysSrcAvg.dimension(thisCFLTRSys.NumOfSurfaces, 0.0);
    1905            5 :                 thisCFLTRSys.LastQRadSysSrc.dimension(thisCFLTRSys.NumOfSurfaces, 0.0);
    1906            5 :                 thisCFLTRSys.LastSysTimeElapsed = 0.0;
    1907            5 :                 thisCFLTRSys.LastTimeStepSys = 0.0;
    1908              :             }
    1909            6 :             for (auto &thisELTRSys : state.dataLowTempRadSys->ElecRadSys) {
    1910            1 :                 thisELTRSys.QRadSysSrcAvg.dimension(thisELTRSys.NumOfSurfaces, 0.0);
    1911            1 :                 thisELTRSys.LastQRadSysSrc.dimension(thisELTRSys.NumOfSurfaces, 0.0);
    1912            1 :                 thisELTRSys.LastSysTimeElapsed = 0.0;
    1913            1 :                 thisELTRSys.LastTimeStepSys = 0.0;
    1914              :             }
    1915            5 :             state.dataLowTempRadSys->MySizeFlagHydr.allocate(state.dataLowTempRadSys->NumOfHydrLowTempRadSys);
    1916            5 :             state.dataLowTempRadSys->MySizeFlagCFlo.allocate(state.dataLowTempRadSys->NumOfCFloLowTempRadSys);
    1917            5 :             state.dataLowTempRadSys->MySizeFlagElec.allocate(state.dataLowTempRadSys->NumOfElecLowTempRadSys);
    1918            5 :             state.dataLowTempRadSys->MySizeFlagHydr = true;
    1919            5 :             state.dataLowTempRadSys->MySizeFlagCFlo = true;
    1920            5 :             state.dataLowTempRadSys->MySizeFlagElec = true;
    1921              : 
    1922              :             // Initialize total areas and ZeroLTRSource for all radiant systems
    1923            6 :             for (auto &thisHRadSys : state.dataLowTempRadSys->HydrRadSys) {
    1924            1 :                 thisHRadSys.ZeroLTRSourceSumHATsurf = 0.0;
    1925            1 :                 thisHRadSys.TotalSurfaceArea = 0.0;
    1926            1 :                 for (int SurfNum = 1; SurfNum <= thisHRadSys.NumOfSurfaces; ++SurfNum) {
    1927            0 :                     thisHRadSys.TotalSurfaceArea += Surface(thisHRadSys.SurfacePtr(SurfNum)).Area;
    1928              :                 }
    1929              :             }
    1930           10 :             for (auto &thisCFLRadSys : state.dataLowTempRadSys->CFloRadSys) {
    1931            5 :                 thisCFLRadSys.ZeroLTRSourceSumHATsurf = 0.0;
    1932            5 :                 thisCFLRadSys.TotalSurfaceArea = 0.0;
    1933            5 :                 for (int SurfNum = 1; SurfNum <= thisCFLRadSys.NumOfSurfaces; ++SurfNum) {
    1934            0 :                     thisCFLRadSys.TotalSurfaceArea += Surface(thisCFLRadSys.SurfacePtr(SurfNum)).Area;
    1935              :                 }
    1936              :             }
    1937            6 :             for (auto &thisERadSys : state.dataLowTempRadSys->ElecRadSys) {
    1938            1 :                 thisERadSys.ZeroLTRSourceSumHATsurf = 0.0;
    1939            1 :                 thisERadSys.TotalSurfaceArea = 0.0;
    1940            1 :                 for (int SurfNum = 1; SurfNum <= thisERadSys.NumOfSurfaces; ++SurfNum) {
    1941            0 :                     thisERadSys.TotalSurfaceArea += Surface(thisERadSys.SurfacePtr(SurfNum)).Area;
    1942              :                 }
    1943              :             }
    1944              : 
    1945            5 :             Real64 MotorEffic(0.0);
    1946            5 :             if (systemType == SystemType::ConstantFlow) {
    1947              :                 // Is there a reason why we were making a copy of this object?
    1948            5 :                 MotorEffic =
    1949            5 :                     state.dataLowTempRadSys->CflowRadiantSysDesign(state.dataLowTempRadSys->CFloRadSys(RadSysNum).DesignObjectPtr).MotorEffic;
    1950              :             }
    1951              : 
    1952              :             // Check pump parameters for constant flow hydronic radiant systems
    1953           10 :             for (auto &thisCFLRadSys : state.dataLowTempRadSys->CFloRadSys) {
    1954              :                 // Calculate the efficiency for each pump: The calculation
    1955              :                 // is based on the PMPSIM code in the ASHRAE Secondary Toolkit
    1956            5 :                 if ((thisCFLRadSys.NomPowerUse > ZeroTol) && (MotorEffic > ZeroTol) && (thisCFLRadSys.WaterVolFlowMax != AutoSize)) {
    1957            4 :                     TotalEffic = thisCFLRadSys.WaterVolFlowMax * thisCFLRadSys.NomPumpHead / thisCFLRadSys.NomPowerUse;
    1958            4 :                     thisCFLRadSys.PumpEffic = TotalEffic / MotorEffic;
    1959            4 :                     constexpr std::string_view fmt = "Check input.  Calc Pump Efficiency={:.5R}% {}, for pump in radiant system {}";
    1960            4 :                     Real64 pumpEfficiency = thisCFLRadSys.PumpEffic * 100.0;
    1961            4 :                     if (thisCFLRadSys.PumpEffic < 0.50) {
    1962            1 :                         ShowWarningError(state, format(fmt, pumpEfficiency, "which is less than 50%", thisCFLRadSys.Name));
    1963            3 :                     } else if ((thisCFLRadSys.PumpEffic > 0.95) && (thisCFLRadSys.PumpEffic <= 1.0)) {
    1964            1 :                         ShowWarningError(state, format(fmt, pumpEfficiency, "is approaching 100%", thisCFLRadSys.Name));
    1965            2 :                     } else if (thisCFLRadSys.PumpEffic > 1.0) {
    1966            1 :                         ShowSevereError(state, format(fmt, pumpEfficiency, "which is bigger than 100%", thisCFLRadSys.Name));
    1967            1 :                         InitErrorsFound = true;
    1968              :                     }
    1969            4 :                 } else {
    1970              :                     // Autosize is not an error but it does not need to check pump efficiency here
    1971            1 :                     if (thisCFLRadSys.WaterVolFlowMax != AutoSize) {
    1972            0 :                         ShowSevereError(state,
    1973            0 :                                         format("Check input.  Pump nominal power and motor efficiency cannot be 0, for pump={}", thisCFLRadSys.Name));
    1974            0 :                         InitErrorsFound = true;
    1975              :                     }
    1976              :                 }
    1977              :             }
    1978              : 
    1979            5 :             state.dataLowTempRadSys->FirstTimeInit = false;
    1980              :         }
    1981              : 
    1982            6 :         if (systemType == SystemType::Hydronic) {
    1983            0 :             if (state.dataLowTempRadSys->MyPlantScanFlagHydr(RadSysNum) && allocated(state.dataPlnt->PlantLoop)) {
    1984            0 :                 errFlag = false;
    1985            0 :                 if (state.dataLowTempRadSys->HydrRadSys(RadSysNum).HotWaterInNode > 0) {
    1986            0 :                     ScanPlantLoopsForObject(state,
    1987            0 :                                             state.dataLowTempRadSys->HydrRadSys(RadSysNum).Name,
    1988              :                                             DataPlant::PlantEquipmentType::LowTempRadiant_VarFlow,
    1989            0 :                                             state.dataLowTempRadSys->HydrRadSys(RadSysNum).HWPlantLoc,
    1990              :                                             errFlag,
    1991              :                                             _,
    1992              :                                             _,
    1993              :                                             _,
    1994            0 :                                             state.dataLowTempRadSys->HydrRadSys(RadSysNum).HotWaterInNode,
    1995              :                                             _);
    1996            0 :                     if (errFlag) {
    1997            0 :                         ShowFatalError(state, "InitLowTempRadiantSystem: Program terminated due to previous condition(s).");
    1998              :                     }
    1999              :                 }
    2000            0 :                 if (state.dataLowTempRadSys->HydrRadSys(RadSysNum).ColdWaterInNode > 0) {
    2001            0 :                     ScanPlantLoopsForObject(state,
    2002            0 :                                             state.dataLowTempRadSys->HydrRadSys(RadSysNum).Name,
    2003              :                                             DataPlant::PlantEquipmentType::LowTempRadiant_VarFlow,
    2004            0 :                                             state.dataLowTempRadSys->HydrRadSys(RadSysNum).CWPlantLoc,
    2005              :                                             errFlag,
    2006              :                                             _,
    2007              :                                             _,
    2008              :                                             _,
    2009            0 :                                             state.dataLowTempRadSys->HydrRadSys(RadSysNum).ColdWaterInNode,
    2010              :                                             _);
    2011            0 :                     if (errFlag) {
    2012            0 :                         ShowFatalError(state, "InitLowTempRadiantSystem: Program terminated due to previous condition(s).");
    2013              :                     }
    2014              :                 }
    2015            0 :                 state.dataLowTempRadSys->MyPlantScanFlagHydr(RadSysNum) = false;
    2016            0 :             } else if (state.dataLowTempRadSys->MyPlantScanFlagHydr(RadSysNum) && !state.dataGlobal->AnyPlantInModel) {
    2017            0 :                 state.dataLowTempRadSys->MyPlantScanFlagHydr(RadSysNum) = false;
    2018              :             }
    2019              : 
    2020            6 :         } else if (systemType == SystemType::ConstantFlow) {
    2021            6 :             if (state.dataLowTempRadSys->MyPlantScanFlagCFlo(RadSysNum) && allocated(state.dataPlnt->PlantLoop)) {
    2022            5 :                 errFlag = false;
    2023            5 :                 if (state.dataLowTempRadSys->CFloRadSys(RadSysNum).HotWaterInNode > 0) {
    2024            0 :                     ScanPlantLoopsForObject(state,
    2025            0 :                                             state.dataLowTempRadSys->CFloRadSys(RadSysNum).Name,
    2026              :                                             DataPlant::PlantEquipmentType::LowTempRadiant_ConstFlow,
    2027            0 :                                             state.dataLowTempRadSys->CFloRadSys(RadSysNum).HWPlantLoc,
    2028              :                                             errFlag,
    2029              :                                             _,
    2030              :                                             _,
    2031              :                                             _,
    2032            0 :                                             state.dataLowTempRadSys->CFloRadSys(RadSysNum).HotWaterInNode,
    2033              :                                             _);
    2034            0 :                     if (errFlag) {
    2035            0 :                         ShowFatalError(state, "InitLowTempRadiantSystem: Program terminated due to previous condition(s).");
    2036              :                     }
    2037              :                 }
    2038            5 :                 if (state.dataLowTempRadSys->CFloRadSys(RadSysNum).ColdWaterInNode > 0) {
    2039            0 :                     ScanPlantLoopsForObject(state,
    2040            0 :                                             state.dataLowTempRadSys->CFloRadSys(RadSysNum).Name,
    2041              :                                             DataPlant::PlantEquipmentType::LowTempRadiant_ConstFlow,
    2042            0 :                                             state.dataLowTempRadSys->CFloRadSys(RadSysNum).CWPlantLoc,
    2043              :                                             errFlag,
    2044              :                                             _,
    2045              :                                             _,
    2046              :                                             _,
    2047            0 :                                             state.dataLowTempRadSys->CFloRadSys(RadSysNum).ColdWaterInNode,
    2048              :                                             _);
    2049            0 :                     if (errFlag) {
    2050            0 :                         ShowFatalError(state, "InitLowTempRadiantSystem: Program terminated due to previous condition(s).");
    2051              :                     }
    2052              :                 }
    2053            5 :                 state.dataLowTempRadSys->MyPlantScanFlagCFlo(RadSysNum) = false;
    2054            1 :             } else if (state.dataLowTempRadSys->MyPlantScanFlagCFlo(RadSysNum) && !state.dataGlobal->AnyPlantInModel) {
    2055            0 :                 state.dataLowTempRadSys->MyPlantScanFlagCFlo(RadSysNum) = false;
    2056              :             }
    2057              :         }
    2058              : 
    2059              :         // need to check all units to see if they are on Zone Equipment List or issue warning
    2060            6 :         if (!state.dataLowTempRadSys->ZoneEquipmentListChecked && state.dataZoneEquip->ZoneEquipInputsFilled) {
    2061            0 :             state.dataLowTempRadSys->ZoneEquipmentListChecked = true;
    2062            0 :             for (auto &thisRadSys : state.dataLowTempRadSys->RadSysTypes) {
    2063            0 :                 switch (thisRadSys.systemType) {
    2064            0 :                 case SystemType::Hydronic: {
    2065            0 :                     if (CheckZoneEquipmentList(state, "ZoneHVAC:LowTemperatureRadiant:VariableFlow", thisRadSys.Name)) continue;
    2066            0 :                     ShowSevereError(state,
    2067            0 :                                     format("InitLowTempRadiantSystem: Unit=[ZoneHVAC:LowTemperatureRadiant:VariableFlow,{}] is not on any "
    2068              :                                            "ZoneHVAC:EquipmentList.  It will not be simulated.",
    2069            0 :                                            thisRadSys.Name));
    2070            0 :                 } break;
    2071            0 :                 case SystemType::ConstantFlow: {
    2072            0 :                     if (CheckZoneEquipmentList(state, "ZoneHVAC:LowTemperatureRadiant:ConstantFlow", thisRadSys.Name)) continue;
    2073            0 :                     ShowSevereError(state,
    2074            0 :                                     format("InitLowTempRadiantSystem: Unit=[ZoneHVAC:LowTemperatureRadiant:ConstantFlow,{}] is not on any "
    2075              :                                            "ZoneHVAC:EquipmentList.  It will not be simulated.",
    2076            0 :                                            thisRadSys.Name));
    2077            0 :                 } break;
    2078            0 :                 case SystemType::Electric: {
    2079            0 :                     if (CheckZoneEquipmentList(state, "ZoneHVAC:LowTemperatureRadiant:Electric", thisRadSys.Name)) continue;
    2080            0 :                     ShowSevereError(state,
    2081            0 :                                     format("InitLowTempRadiantSystem: Unit=[ZoneHVAC:LowTemperatureRadiant:Electric,{}] is not on any "
    2082              :                                            "ZoneHVAC:EquipmentList.  It will not be simulated.",
    2083            0 :                                            thisRadSys.Name));
    2084            0 :                 } break;
    2085            0 :                 default: { // Illegal system, but checked earlier
    2086            0 :                 } break;
    2087              :                 }
    2088              :             }
    2089              :         }
    2090              : 
    2091            6 :         if (!state.dataGlobal->SysSizingCalc && (systemType == SystemType::Hydronic)) {
    2092            0 :             if (state.dataLowTempRadSys->MySizeFlagHydr(RadSysNum) && !state.dataLowTempRadSys->MyPlantScanFlagHydr(RadSysNum)) {
    2093              :                 // for each radiant system do the sizing once.
    2094            0 :                 SizeLowTempRadiantSystem(state, RadSysNum, systemType);
    2095            0 :                 state.dataLowTempRadSys->MySizeFlagHydr(RadSysNum) = false;
    2096              : 
    2097            0 :                 Sched::Schedule *coldSetptSched = nullptr, *hotSetptSched = nullptr;
    2098            0 :                 if (systemType == SystemType::Hydronic) {
    2099            0 :                     VarFlowRadDesignData variableFlowDesignDataObject{state.dataLowTempRadSys->HydronicRadiantSysDesign(
    2100            0 :                         state.dataLowTempRadSys->HydrRadSys(RadSysNum).DesignObjectPtr)}; // Contains the data for variable flow hydronic systems;
    2101            0 :                     coldSetptSched = variableFlowDesignDataObject.coolSetptSched;
    2102            0 :                     hotSetptSched = variableFlowDesignDataObject.heatSetptSched;
    2103            0 :                 }
    2104              : 
    2105              :                 // Can this system actually do cooling?
    2106            0 :                 if ((state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterVolFlowMaxCool > 0.0) &&
    2107            0 :                     (state.dataLowTempRadSys->HydrRadSys(RadSysNum).ColdWaterInNode > 0) &&
    2108            0 :                     (state.dataLowTempRadSys->HydrRadSys(RadSysNum).ColdWaterOutNode > 0) && (coldSetptSched != nullptr)) {
    2109            0 :                     state.dataLowTempRadSys->HydrRadSys(RadSysNum).CoolingSystem = true;
    2110              :                 }
    2111              : 
    2112              :                 // Can this system actually do heating?
    2113            0 :                 if ((state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterVolFlowMaxHeat > 0.0) &&
    2114            0 :                     (state.dataLowTempRadSys->HydrRadSys(RadSysNum).HotWaterInNode > 0) &&
    2115            0 :                     (state.dataLowTempRadSys->HydrRadSys(RadSysNum).HotWaterOutNode > 0) && (hotSetptSched != nullptr)) {
    2116            0 :                     state.dataLowTempRadSys->HydrRadSys(RadSysNum).HeatingSystem = true;
    2117              :                 }
    2118              : 
    2119              :                 // set design mass flow rates
    2120            0 :                 if (state.dataLowTempRadSys->HydrRadSys(RadSysNum).HotWaterInNode > 0) {
    2121            0 :                     rho = state.dataPlnt->PlantLoop(state.dataLowTempRadSys->HydrRadSys(RadSysNum).HWPlantLoc.loopNum)
    2122            0 :                               .glycol->getDensity(state, Constant::HWInitConvTemp, RoutineName);
    2123            0 :                     state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterFlowMaxHeat =
    2124            0 :                         rho * state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterVolFlowMaxHeat;
    2125            0 :                     InitComponentNodes(state,
    2126              :                                        0.0,
    2127            0 :                                        state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterFlowMaxHeat,
    2128            0 :                                        state.dataLowTempRadSys->HydrRadSys(RadSysNum).HotWaterInNode,
    2129            0 :                                        state.dataLowTempRadSys->HydrRadSys(RadSysNum).HotWaterOutNode);
    2130              :                 }
    2131            0 :                 if (state.dataLowTempRadSys->HydrRadSys(RadSysNum).ColdWaterInNode > 0) {
    2132            0 :                     rho = state.dataPlnt->PlantLoop(state.dataLowTempRadSys->HydrRadSys(RadSysNum).CWPlantLoc.loopNum)
    2133            0 :                               .glycol->getDensity(state, Constant::CWInitConvTemp, RoutineName);
    2134            0 :                     state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterFlowMaxCool =
    2135            0 :                         rho * state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterVolFlowMaxCool;
    2136            0 :                     InitComponentNodes(state,
    2137              :                                        0.0,
    2138            0 :                                        state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterFlowMaxCool,
    2139            0 :                                        state.dataLowTempRadSys->HydrRadSys(RadSysNum).ColdWaterInNode,
    2140            0 :                                        state.dataLowTempRadSys->HydrRadSys(RadSysNum).ColdWaterOutNode);
    2141              :                 }
    2142              :             }
    2143              :         }
    2144              : 
    2145            6 :         if (!state.dataGlobal->SysSizingCalc && (systemType == SystemType::ConstantFlow)) {
    2146            6 :             if (state.dataLowTempRadSys->MySizeFlagCFlo(RadSysNum) && !state.dataLowTempRadSys->MyPlantScanFlagCFlo(RadSysNum)) {
    2147              :                 // for each radiant system do the sizing once.
    2148            5 :                 SizeLowTempRadiantSystem(state, RadSysNum, systemType);
    2149              : 
    2150              :                 // set design mass flow rates
    2151            5 :                 if (state.dataLowTempRadSys->CFloRadSys(RadSysNum).HotWaterInNode > 0) {
    2152            0 :                     rho = state.dataPlnt->PlantLoop(state.dataLowTempRadSys->CFloRadSys(RadSysNum).HWPlantLoc.loopNum)
    2153            0 :                               .glycol->getDensity(state, Constant::HWInitConvTemp, RoutineName);
    2154            0 :                     state.dataLowTempRadSys->CFloRadSys(RadSysNum).HotDesignWaterMassFlowRate =
    2155            0 :                         rho * state.dataLowTempRadSys->CFloRadSys(RadSysNum).WaterVolFlowMax;
    2156            0 :                     InitComponentNodes(state,
    2157              :                                        0.0,
    2158            0 :                                        state.dataLowTempRadSys->CFloRadSys(RadSysNum).HotDesignWaterMassFlowRate,
    2159            0 :                                        state.dataLowTempRadSys->CFloRadSys(RadSysNum).HotWaterInNode,
    2160            0 :                                        state.dataLowTempRadSys->CFloRadSys(RadSysNum).HotWaterOutNode);
    2161              :                 }
    2162            5 :                 if (state.dataLowTempRadSys->CFloRadSys(RadSysNum).ColdWaterInNode > 0) {
    2163            0 :                     rho = state.dataPlnt->PlantLoop(state.dataLowTempRadSys->CFloRadSys(RadSysNum).CWPlantLoc.loopNum)
    2164            0 :                               .glycol->getDensity(state, Constant::CWInitConvTemp, RoutineName);
    2165            0 :                     state.dataLowTempRadSys->CFloRadSys(RadSysNum).ColdDesignWaterMassFlowRate =
    2166            0 :                         rho * state.dataLowTempRadSys->CFloRadSys(RadSysNum).WaterVolFlowMax;
    2167            0 :                     InitComponentNodes(state,
    2168              :                                        0.0,
    2169            0 :                                        state.dataLowTempRadSys->CFloRadSys(RadSysNum).ColdDesignWaterMassFlowRate,
    2170            0 :                                        state.dataLowTempRadSys->CFloRadSys(RadSysNum).ColdWaterInNode,
    2171            0 :                                        state.dataLowTempRadSys->CFloRadSys(RadSysNum).ColdWaterOutNode);
    2172              :                 }
    2173            5 :                 state.dataLowTempRadSys->MySizeFlagCFlo(RadSysNum) = false;
    2174              :             }
    2175              :         }
    2176              : 
    2177            6 :         if (!state.dataGlobal->SysSizingCalc && (systemType == SystemType::Electric)) {
    2178            0 :             if (state.dataLowTempRadSys->MySizeFlagElec(RadSysNum)) {
    2179              :                 // for each radiant system do the sizing once.
    2180            0 :                 SizeLowTempRadiantSystem(state, RadSysNum, systemType);
    2181            0 :                 state.dataLowTempRadSys->MySizeFlagElec(RadSysNum) = false;
    2182              :             }
    2183              :         }
    2184              : 
    2185            6 :         if (state.dataGlobal->BeginEnvrnFlag && state.dataLowTempRadSys->MyEnvrnFlagGeneral) {
    2186            0 :             if (systemType == SystemType::Hydronic) {
    2187            0 :                 auto &thisLTR = state.dataLowTempRadSys->HydrRadSys(RadSysNum);
    2188            0 :                 thisLTR.ZeroLTRSourceSumHATsurf = 0.0;
    2189            0 :                 thisLTR.QRadSysSrcAvg = 0.0;
    2190            0 :                 thisLTR.LastQRadSysSrc = 0.0;
    2191            0 :                 thisLTR.LastSysTimeElapsed = 0.0;
    2192            0 :                 thisLTR.LastTimeStepSys = 0.0;
    2193            0 :             } else if (systemType == SystemType::ConstantFlow) {
    2194            0 :                 auto &thisLTR = state.dataLowTempRadSys->CFloRadSys(RadSysNum);
    2195            0 :                 thisLTR.ZeroLTRSourceSumHATsurf = 0.0;
    2196            0 :                 thisLTR.QRadSysSrcAvg = 0.0;
    2197            0 :                 thisLTR.LastQRadSysSrc = 0.0;
    2198            0 :                 thisLTR.LastSysTimeElapsed = 0.0;
    2199            0 :                 thisLTR.LastTimeStepSys = 0.0;
    2200            0 :             } else if (systemType == SystemType::Electric) {
    2201            0 :                 auto &thisLTR = state.dataLowTempRadSys->ElecRadSys(RadSysNum);
    2202            0 :                 thisLTR.ZeroLTRSourceSumHATsurf = 0.0;
    2203            0 :                 thisLTR.QRadSysSrcAvg = 0.0;
    2204            0 :                 thisLTR.LastQRadSysSrc = 0.0;
    2205            0 :                 thisLTR.LastSysTimeElapsed = 0.0;
    2206            0 :                 thisLTR.LastTimeStepSys = 0.0;
    2207              :             }
    2208            0 :             state.dataLowTempRadSys->MyEnvrnFlagGeneral = false;
    2209              :         }
    2210            6 :         if (!state.dataGlobal->BeginEnvrnFlag) state.dataLowTempRadSys->MyEnvrnFlagGeneral = true;
    2211              : 
    2212              :         // If we are at the beginning of a new environment OR the warmup period is done and the simulation is starting,
    2213              :         // then the various changeover variables need to be reset so that we are starting from scratch.
    2214           12 :         if ((state.dataGlobal->BeginEnvrnFlag && FirstHVACIteration) ||
    2215            6 :             (!state.dataGlobal->WarmupFlag && state.dataGlobal->BeginDayFlag && FirstHVACIteration && state.dataGlobal->DayOfSim == 1)) {
    2216              :             // Reset values related to changeover
    2217            0 :             if (systemType == SystemType::Hydronic) {
    2218            0 :                 state.dataLowTempRadSys->HydrRadSys(RadSysNum).lastOpMode = OpMode::None;
    2219            0 :                 state.dataLowTempRadSys->HydrRadSys(RadSysNum).lastDayOfSim = 0;
    2220            0 :                 state.dataLowTempRadSys->HydrRadSys(RadSysNum).lastHourOfDay = 0;
    2221            0 :                 state.dataLowTempRadSys->HydrRadSys(RadSysNum).lastTimeStep = 0;
    2222              :             }
    2223            0 :             if (systemType == SystemType::ConstantFlow) {
    2224            0 :                 state.dataLowTempRadSys->CFloRadSys(RadSysNum).lastOpMode = OpMode::None;
    2225            0 :                 state.dataLowTempRadSys->CFloRadSys(RadSysNum).lastDayOfSim = 0;
    2226            0 :                 state.dataLowTempRadSys->CFloRadSys(RadSysNum).lastHourOfDay = 0;
    2227            0 :                 state.dataLowTempRadSys->CFloRadSys(RadSysNum).lastTimeStep = 0;
    2228              :             }
    2229              :         }
    2230              : 
    2231            6 :         if (systemType == SystemType::Hydronic) {
    2232            0 :             if (state.dataGlobal->BeginEnvrnFlag && state.dataLowTempRadSys->MyEnvrnFlagHydr(RadSysNum)) {
    2233            0 :                 state.dataLowTempRadSys->HydrRadSys(RadSysNum).HeatPower = 0.0;
    2234            0 :                 state.dataLowTempRadSys->HydrRadSys(RadSysNum).HeatEnergy = 0.0;
    2235            0 :                 state.dataLowTempRadSys->HydrRadSys(RadSysNum).CoolPower = 0.0;
    2236            0 :                 state.dataLowTempRadSys->HydrRadSys(RadSysNum).CoolEnergy = 0.0;
    2237            0 :                 state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterInletTemp = 0.0;
    2238            0 :                 state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterOutletTemp = 0.0;
    2239            0 :                 state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterMassFlowRate = 0.0;
    2240              : 
    2241            0 :                 if (!state.dataLowTempRadSys->MyPlantScanFlagHydr(RadSysNum)) {
    2242            0 :                     if (state.dataLowTempRadSys->HydrRadSys(RadSysNum).HotWaterInNode > 0) {
    2243            0 :                         InitComponentNodes(state,
    2244              :                                            0.0,
    2245            0 :                                            state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterFlowMaxHeat,
    2246            0 :                                            state.dataLowTempRadSys->HydrRadSys(RadSysNum).HotWaterInNode,
    2247            0 :                                            state.dataLowTempRadSys->HydrRadSys(RadSysNum).HotWaterOutNode);
    2248              :                     }
    2249            0 :                     if (state.dataLowTempRadSys->HydrRadSys(RadSysNum).ColdWaterInNode > 0) {
    2250            0 :                         InitComponentNodes(state,
    2251              :                                            0.0,
    2252            0 :                                            state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterFlowMaxCool,
    2253            0 :                                            state.dataLowTempRadSys->HydrRadSys(RadSysNum).ColdWaterInNode,
    2254            0 :                                            state.dataLowTempRadSys->HydrRadSys(RadSysNum).ColdWaterOutNode);
    2255              :                     }
    2256              :                 }
    2257            0 :                 state.dataLowTempRadSys->MyEnvrnFlagHydr(RadSysNum) = false;
    2258              :             }
    2259              :         } // NumOfHydrLowTempRadSys > 0
    2260            6 :         if (!state.dataGlobal->BeginEnvrnFlag && systemType == SystemType::Hydronic) state.dataLowTempRadSys->MyEnvrnFlagHydr(RadSysNum) = true;
    2261              : 
    2262            6 :         if (systemType == SystemType::ConstantFlow) {
    2263            6 :             if (state.dataGlobal->BeginEnvrnFlag && state.dataLowTempRadSys->MyEnvrnFlagCFlo(RadSysNum)) {
    2264            0 :                 state.dataLowTempRadSys->CFloRadSys(RadSysNum).WaterInletTemp = 0.0;
    2265            0 :                 state.dataLowTempRadSys->CFloRadSys(RadSysNum).WaterOutletTemp = 0.0;
    2266            0 :                 state.dataLowTempRadSys->CFloRadSys(RadSysNum).PumpInletTemp = 0.0;
    2267            0 :                 state.dataLowTempRadSys->CFloRadSys(RadSysNum).WaterMassFlowRate = 0.0;
    2268            0 :                 state.dataLowTempRadSys->CFloRadSys(RadSysNum).WaterInjectionRate = 0.0;
    2269            0 :                 state.dataLowTempRadSys->CFloRadSys(RadSysNum).WaterRecircRate = 0.0;
    2270            0 :                 state.dataLowTempRadSys->CFloRadSys(RadSysNum).HeatPower = 0.0;
    2271            0 :                 state.dataLowTempRadSys->CFloRadSys(RadSysNum).HeatEnergy = 0.0;
    2272            0 :                 state.dataLowTempRadSys->CFloRadSys(RadSysNum).CoolPower = 0.0;
    2273            0 :                 state.dataLowTempRadSys->CFloRadSys(RadSysNum).CoolEnergy = 0.0;
    2274            0 :                 state.dataLowTempRadSys->CFloRadSys(RadSysNum).PumpPower = 0.0;
    2275            0 :                 state.dataLowTempRadSys->CFloRadSys(RadSysNum).PumpMassFlowRate = 0.0;
    2276            0 :                 state.dataLowTempRadSys->CFloRadSys(RadSysNum).PumpHeattoFluid = 0.0;
    2277              : 
    2278            0 :                 if (!state.dataLowTempRadSys->MyPlantScanFlagCFlo(RadSysNum)) {
    2279            0 :                     if (state.dataLowTempRadSys->CFloRadSys(RadSysNum).HotWaterInNode > 0) {
    2280            0 :                         InitComponentNodes(state,
    2281              :                                            0.0,
    2282            0 :                                            state.dataLowTempRadSys->CFloRadSys(RadSysNum).HotDesignWaterMassFlowRate,
    2283            0 :                                            state.dataLowTempRadSys->CFloRadSys(RadSysNum).HotWaterInNode,
    2284            0 :                                            state.dataLowTempRadSys->CFloRadSys(RadSysNum).HotWaterOutNode);
    2285              :                     }
    2286            0 :                     if (state.dataLowTempRadSys->CFloRadSys(RadSysNum).ColdWaterInNode > 0) {
    2287            0 :                         InitComponentNodes(state,
    2288              :                                            0.0,
    2289            0 :                                            state.dataLowTempRadSys->CFloRadSys(RadSysNum).ColdDesignWaterMassFlowRate,
    2290            0 :                                            state.dataLowTempRadSys->CFloRadSys(RadSysNum).ColdWaterInNode,
    2291            0 :                                            state.dataLowTempRadSys->CFloRadSys(RadSysNum).ColdWaterOutNode);
    2292              :                     }
    2293              :                 }
    2294            0 :                 state.dataLowTempRadSys->MyEnvrnFlagCFlo(RadSysNum) = false;
    2295              :             }
    2296              : 
    2297            6 :             if (state.dataLowTempRadSys->anyRadiantSystemUsingRunningMeanAverage) {
    2298            0 :                 if (state.dataGlobal->BeginDayFlag && state.dataLowTempRadSys->CFloRadSys(RadSysNum).setRunningMeanValuesAtBeginningOfDay) {
    2299            0 :                     state.dataLowTempRadSys->CFloRadSys(RadSysNum).calculateRunningMeanAverageTemperature(state, RadSysNum);
    2300            0 :                     state.dataLowTempRadSys->CFloRadSys(RadSysNum).setRunningMeanValuesAtBeginningOfDay = false; // only set these once per system
    2301            0 :                 } else if (!state.dataGlobal->BeginDayFlag && !state.dataLowTempRadSys->CFloRadSys(RadSysNum).setRunningMeanValuesAtBeginningOfDay) {
    2302            0 :                     state.dataLowTempRadSys->CFloRadSys(RadSysNum).setRunningMeanValuesAtBeginningOfDay =
    2303              :                         true; // reset so that the next time BeginDayFlag is true this can get set
    2304              :                 }
    2305              :             }
    2306              : 
    2307              :         } // NumOfCFloLowTempRadSys > 0
    2308            6 :         if (!state.dataGlobal->BeginEnvrnFlag && systemType == SystemType::ConstantFlow) state.dataLowTempRadSys->MyEnvrnFlagCFlo(RadSysNum) = true;
    2309              : 
    2310            6 :         if (systemType == SystemType::Electric) {
    2311            0 :             if (state.dataGlobal->BeginEnvrnFlag && state.dataLowTempRadSys->MyEnvrnFlagElec(RadSysNum)) {
    2312            0 :                 state.dataLowTempRadSys->ElecRadSys(RadSysNum).HeatPower = 0.0;
    2313            0 :                 state.dataLowTempRadSys->ElecRadSys(RadSysNum).HeatEnergy = 0.0;
    2314            0 :                 state.dataLowTempRadSys->ElecRadSys(RadSysNum).ElecPower = 0.0;
    2315            0 :                 state.dataLowTempRadSys->ElecRadSys(RadSysNum).ElecEnergy = 0.0;
    2316              :             }
    2317            0 :             state.dataLowTempRadSys->MyEnvrnFlagElec(RadSysNum) = false;
    2318              :         }
    2319            6 :         if (!state.dataGlobal->BeginEnvrnFlag && systemType == SystemType::Electric) state.dataLowTempRadSys->MyEnvrnFlagElec(RadSysNum) = true;
    2320              : 
    2321            6 :         if (systemType == SystemType::ConstantFlow) {
    2322              : 
    2323              :             // Can this system actually do heating?
    2324            6 :             if ((state.dataLowTempRadSys->CFloRadSys(RadSysNum).WaterVolFlowMax > 0.0) &&
    2325            5 :                 (state.dataLowTempRadSys->CFloRadSys(RadSysNum).HotWaterInNode > 0) &&
    2326            0 :                 (state.dataLowTempRadSys->CFloRadSys(RadSysNum).HotWaterOutNode > 0) &&
    2327            0 :                 (state.dataLowTempRadSys->CFloRadSys(RadSysNum).hotWaterHiTempSched != nullptr) &&
    2328            0 :                 (state.dataLowTempRadSys->CFloRadSys(RadSysNum).hotWaterLoTempSched != nullptr) &&
    2329           11 :                 (state.dataLowTempRadSys->CFloRadSys(RadSysNum).hotCtrlHiTempSched != nullptr) &&
    2330            0 :                 (state.dataLowTempRadSys->CFloRadSys(RadSysNum).hotCtrlLoTempSched != nullptr)) {
    2331            0 :                 state.dataLowTempRadSys->CFloRadSys(RadSysNum).HeatingSystem = true;
    2332              :             }
    2333              : 
    2334              :             // Can this system actually do cooling?
    2335            6 :             if ((state.dataLowTempRadSys->CFloRadSys(RadSysNum).WaterVolFlowMax > 0.0) &&
    2336            5 :                 (state.dataLowTempRadSys->CFloRadSys(RadSysNum).ColdWaterInNode > 0) &&
    2337            0 :                 (state.dataLowTempRadSys->CFloRadSys(RadSysNum).ColdWaterOutNode > 0) &&
    2338            0 :                 (state.dataLowTempRadSys->CFloRadSys(RadSysNum).coldWaterHiTempSched != nullptr) &&
    2339            0 :                 (state.dataLowTempRadSys->CFloRadSys(RadSysNum).coldWaterLoTempSched != nullptr) &&
    2340           11 :                 (state.dataLowTempRadSys->CFloRadSys(RadSysNum).coldCtrlHiTempSched != nullptr) &&
    2341            0 :                 (state.dataLowTempRadSys->CFloRadSys(RadSysNum).coldCtrlLoTempSched != nullptr)) {
    2342            0 :                 state.dataLowTempRadSys->CFloRadSys(RadSysNum).CoolingSystem = true;
    2343              :             }
    2344              :         }
    2345              : 
    2346            6 :         if (state.dataGlobal->BeginTimeStepFlag && FirstHVACIteration) { // This is the first pass through in a particular time step
    2347              : 
    2348            0 :             switch (systemType) {
    2349            0 :             case SystemType::Hydronic: {
    2350            0 :                 int ZoneNum = state.dataLowTempRadSys->HydrRadSys(RadSysNum).ZonePtr;
    2351            0 :                 auto &thisLTR = state.dataLowTempRadSys->HydrRadSys(RadSysNum);
    2352            0 :                 thisLTR.ZeroLTRSourceSumHATsurf =
    2353            0 :                     state.dataHeatBal->Zone(ZoneNum).sumHATsurf(state); // Set this to figure what part of the load the radiant system meets
    2354            0 :                 thisLTR.QRadSysSrcAvg = 0.0;                            // Initialize this variable to zero (radiant system defaults to off)
    2355            0 :                 thisLTR.LastQRadSysSrc = 0.0;     // At the start of a time step, reset to zero so average calculation can begin again
    2356            0 :                 thisLTR.LastSysTimeElapsed = 0.0; // At the start of a time step, reset to zero so average calculation can begin again
    2357            0 :                 thisLTR.LastTimeStepSys = 0.0; // At the start of a time step, reset to zero so average calculation can begin again                }
    2358            0 :             } break;
    2359            0 :             case SystemType::ConstantFlow: {
    2360            0 :                 int ZoneNum = state.dataLowTempRadSys->CFloRadSys(RadSysNum).ZonePtr;
    2361            0 :                 auto &thisLTR = state.dataLowTempRadSys->CFloRadSys(RadSysNum);
    2362            0 :                 thisLTR.ZeroLTRSourceSumHATsurf =
    2363            0 :                     state.dataHeatBal->Zone(ZoneNum).sumHATsurf(state); // Set this to figure what part of the load the radiant system meets
    2364            0 :                 thisLTR.QRadSysSrcAvg = 0.0;                            // Initialize this variable to zero (radiant system defaults to off)
    2365            0 :                 thisLTR.LastQRadSysSrc = 0.0;     // At the start of a time step, reset to zero so average calculation can begin again
    2366            0 :                 thisLTR.LastSysTimeElapsed = 0.0; // At the start of a time step, reset to zero so average calculation can begin again
    2367            0 :                 thisLTR.LastTimeStepSys = 0.0; // At the start of a time step, reset to zero so average calculation can begin again                }
    2368            0 :             } break;
    2369            0 :             case SystemType::Electric: {
    2370            0 :                 int ZoneNum = state.dataLowTempRadSys->ElecRadSys(RadSysNum).ZonePtr;
    2371            0 :                 auto &thisLTR = state.dataLowTempRadSys->ElecRadSys(RadSysNum);
    2372            0 :                 thisLTR.ZeroLTRSourceSumHATsurf =
    2373            0 :                     state.dataHeatBal->Zone(ZoneNum).sumHATsurf(state); // Set this to figure what part of the load the radiant system meets
    2374            0 :                 thisLTR.QRadSysSrcAvg = 0.0;                            // Initialize this variable to zero (radiant system defaults to off)
    2375            0 :                 thisLTR.LastQRadSysSrc = 0.0;     // At the start of a time step, reset to zero so average calculation can begin again
    2376            0 :                 thisLTR.LastSysTimeElapsed = 0.0; // At the start of a time step, reset to zero so average calculation can begin again
    2377            0 :                 thisLTR.LastTimeStepSys = 0.0; // At the start of a time step, reset to zero so average calculation can begin again                }
    2378            0 :             } break;
    2379            0 :             default: {
    2380            0 :                 ShowSevereError(state, "Radiant system entered without specification of type: electric, constant flow, or hydronic?");
    2381            0 :                 ShowContinueError(state, format("Occurs in Radiant System={}", state.dataLowTempRadSys->HydrRadSys(RadSysNum).Name));
    2382            0 :                 ShowFatalError(state, "Preceding condition causes termination.");
    2383            0 :             } break;
    2384              :             }
    2385              : 
    2386              :         } // ...for first pass through in a particular time step.
    2387              : 
    2388            6 :         switch (systemType) {
    2389              : 
    2390            0 :         case SystemType::Hydronic: {
    2391              : 
    2392              :             // Initialize the appropriate node data
    2393            0 :             if (state.dataLowTempRadSys->HydrRadSys(RadSysNum).HeatingSystem) {
    2394            0 :                 mdot = 0.0;
    2395            0 :                 SetComponentFlowRate(state,
    2396              :                                      mdot,
    2397            0 :                                      state.dataLowTempRadSys->HydrRadSys(RadSysNum).HotWaterInNode,
    2398            0 :                                      state.dataLowTempRadSys->HydrRadSys(RadSysNum).HotWaterOutNode,
    2399            0 :                                      state.dataLowTempRadSys->HydrRadSys(RadSysNum).HWPlantLoc);
    2400              :             }
    2401            0 :             if (state.dataLowTempRadSys->HydrRadSys(RadSysNum).CoolingSystem) {
    2402            0 :                 mdot = 0.0;
    2403            0 :                 SetComponentFlowRate(state,
    2404              :                                      mdot,
    2405            0 :                                      state.dataLowTempRadSys->HydrRadSys(RadSysNum).ColdWaterInNode,
    2406            0 :                                      state.dataLowTempRadSys->HydrRadSys(RadSysNum).ColdWaterOutNode,
    2407            0 :                                      state.dataLowTempRadSys->HydrRadSys(RadSysNum).CWPlantLoc);
    2408              :             }
    2409            0 :             if (state.dataLowTempRadSys->HydrRadSys(RadSysNum).opMode != OpMode::None && FirstHVACIteration)
    2410            0 :                 state.dataLowTempRadSys->HydrRadSys(RadSysNum).updateOperatingModeHistory(state);
    2411              : 
    2412            0 :         } break;
    2413              : 
    2414            6 :         case SystemType::ConstantFlow: {
    2415            6 :             state.dataLowTempRadSys->CFloRadSys(RadSysNum).WaterMassFlowRate = 0.0;
    2416              :             // Initialize the appropriate node data
    2417            6 :             if (state.dataLowTempRadSys->CFloRadSys(RadSysNum).HeatingSystem) {
    2418            1 :                 if (state.dataLowTempRadSys->CFloRadSys(RadSysNum).volFlowSched != nullptr) {
    2419            0 :                     CurrentFlowSchedule = state.dataLowTempRadSys->CFloRadSys(RadSysNum).volFlowSched->getCurrentVal();
    2420              :                 } else {
    2421            1 :                     CurrentFlowSchedule = 1.0; // Allow user to avoid putting in a schedule (defaults to constant flow at all times)
    2422              :                 }
    2423            1 :                 if (CurrentFlowSchedule > 1.0) CurrentFlowSchedule = 1.0; // Do not allow more flow than design maximum
    2424            1 :                 if (CurrentFlowSchedule < 0.0) CurrentFlowSchedule = 0.0; // Do not allow negative flow
    2425              : 
    2426            1 :                 state.dataLowTempRadSys->CFloRadSys(RadSysNum).HotWaterMassFlowRate =
    2427            1 :                     state.dataLowTempRadSys->CFloRadSys(RadSysNum).HotDesignWaterMassFlowRate * CurrentFlowSchedule;
    2428              : 
    2429            1 :                 if (state.dataLowTempRadSys->CFloRadSys(RadSysNum).EMSOverrideOnWaterMdot)
    2430            0 :                     state.dataLowTempRadSys->CFloRadSys(RadSysNum).HotWaterMassFlowRate =
    2431            0 :                         state.dataLowTempRadSys->CFloRadSys(RadSysNum).EMSWaterMdotOverrideValue;
    2432              : 
    2433            1 :                 if (state.dataLowTempRadSys->CFloRadSys(RadSysNum).HotWaterInNode > 0)
    2434            0 :                     SetComponentFlowRate(state,
    2435            0 :                                          state.dataLowTempRadSys->CFloRadSys(RadSysNum).HotWaterMassFlowRate,
    2436            0 :                                          state.dataLowTempRadSys->CFloRadSys(RadSysNum).HotWaterInNode,
    2437            0 :                                          state.dataLowTempRadSys->CFloRadSys(RadSysNum).HotWaterOutNode,
    2438            0 :                                          state.dataLowTempRadSys->CFloRadSys(RadSysNum).HWPlantLoc);
    2439              :             }
    2440            6 :             if (state.dataLowTempRadSys->CFloRadSys(RadSysNum).CoolingSystem) {
    2441            1 :                 if (state.dataLowTempRadSys->CFloRadSys(RadSysNum).volFlowSched != nullptr) {
    2442            0 :                     CurrentFlowSchedule = state.dataLowTempRadSys->CFloRadSys(RadSysNum).volFlowSched->getCurrentVal();
    2443              :                 } else {
    2444            1 :                     CurrentFlowSchedule = 1.0; // Allow user to avoid putting in a schedule (defaults to constant flow at all times)
    2445              :                 }
    2446            1 :                 if (CurrentFlowSchedule > 1.0) CurrentFlowSchedule = 1.0; // Do not allow more flow than design maximum
    2447            1 :                 if (CurrentFlowSchedule < 0.0) CurrentFlowSchedule = 0.0; // Do not allow negative flow
    2448            1 :                 state.dataLowTempRadSys->CFloRadSys(RadSysNum).ChWaterMassFlowRate =
    2449            1 :                     state.dataLowTempRadSys->CFloRadSys(RadSysNum).ColdDesignWaterMassFlowRate * CurrentFlowSchedule;
    2450              : 
    2451            1 :                 if (state.dataLowTempRadSys->CFloRadSys(RadSysNum).EMSOverrideOnWaterMdot)
    2452            0 :                     state.dataLowTempRadSys->CFloRadSys(RadSysNum).ChWaterMassFlowRate =
    2453            0 :                         state.dataLowTempRadSys->CFloRadSys(RadSysNum).EMSWaterMdotOverrideValue;
    2454              : 
    2455            1 :                 if (state.dataLowTempRadSys->CFloRadSys(RadSysNum).ColdWaterInNode > 0)
    2456            0 :                     SetComponentFlowRate(state,
    2457            0 :                                          state.dataLowTempRadSys->CFloRadSys(RadSysNum).ChWaterMassFlowRate,
    2458            0 :                                          state.dataLowTempRadSys->CFloRadSys(RadSysNum).ColdWaterInNode,
    2459            0 :                                          state.dataLowTempRadSys->CFloRadSys(RadSysNum).ColdWaterOutNode,
    2460            0 :                                          state.dataLowTempRadSys->CFloRadSys(RadSysNum).CWPlantLoc);
    2461              :             }
    2462            6 :             if (state.dataLowTempRadSys->CFloRadSys(RadSysNum).opMode != OpMode::None && FirstHVACIteration)
    2463            0 :                 state.dataLowTempRadSys->CFloRadSys(RadSysNum).updateOperatingModeHistory(state);
    2464              : 
    2465            6 :         } break;
    2466            0 :         case SystemType::Electric: {
    2467            0 :             state.dataLowTempRadSys->ElecRadSys(RadSysNum).opMode = OpMode::None;
    2468            0 :         } break;
    2469            0 :         default:
    2470            0 :             break;
    2471              :         }
    2472            6 :     }
    2473              : 
    2474            4 :     void HydronicSystemBaseData::updateOperatingModeHistory(EnergyPlusData &state)
    2475              :     {
    2476              :         // Since this is only called when the operating mode is something other than "not operating",
    2477              :         // the status from the previous system time step is what it did in the last or previous time step.
    2478              :         // So, we can update the last status of the system using this information before resetting things
    2479              :         // to "not operating".
    2480            4 :         this->lastOpMode = this->opMode;
    2481              : 
    2482            4 :         if (state.dataGlobal->BeginDayFlag) {
    2483              :             // The begin day flag is set which mean this is the first time step of the day.
    2484              :             // This also means that the previous time step was the last time step of yesterday.
    2485              :             // So, the day should be the previous day, the hour should be the last hour of the
    2486              :             // day, and the time step should be the last time step.
    2487            1 :             this->lastDayOfSim = state.dataGlobal->DayOfSim - 1;
    2488            1 :             this->lastHourOfDay = Constant::iHoursInDay;
    2489            1 :             this->lastTimeStep = state.dataGlobal->TimeStepsInHour;
    2490            3 :         } else if (state.dataGlobal->BeginHourFlag) {
    2491              :             // It's not the beginning of the day but it is the beginning of an hour other than
    2492              :             // the first hour.  This means that the previous time step was the previous hour of
    2493              :             // today in the last time step.  So, the day should be the current day, the hour should
    2494              :             // be the previous hour, and the time step should be the last time step.
    2495            1 :             this->lastDayOfSim = state.dataGlobal->DayOfSim;
    2496            1 :             this->lastHourOfDay = state.dataGlobal->HourOfDay - 1;
    2497            1 :             this->lastTimeStep = state.dataGlobal->TimeStepsInHour;
    2498            2 :         } else if (state.dataGlobal->BeginTimeStepFlag) {
    2499              :             // It's neither the beginning of the day nor the beginning of an hour but it is the start
    2500              :             // of a time step other than the first time step in the hour.  So, the day should be the
    2501              :             // current day, the hour should be the current hour, and the time step should be the
    2502              :             // previous time step.
    2503            1 :             this->lastDayOfSim = state.dataGlobal->DayOfSim;
    2504            1 :             this->lastHourOfDay = state.dataGlobal->HourOfDay;
    2505            1 :             this->lastTimeStep = state.dataGlobal->TimeStep - 1;
    2506              :         } else {
    2507              :             // It's not the beginning of the day, hour, or time step so the "last" value is simply the
    2508              :             // same as the current value.  Note that these parameters only track down to the zone time
    2509              :             // step level and will make decisions based on that.
    2510            1 :             this->lastDayOfSim = state.dataGlobal->DayOfSim;
    2511            1 :             this->lastHourOfDay = state.dataGlobal->HourOfDay;
    2512            1 :             this->lastTimeStep = state.dataGlobal->TimeStep;
    2513              :         }
    2514              : 
    2515              :         // Now go ahead and reset the operating mode (this will be set to something else if the system is running)
    2516            4 :         this->opMode = OpMode::None;
    2517            4 :     }
    2518              : 
    2519           10 :     void HydronicSystemBaseData::setOperatingModeBasedOnChangeoverDelay(EnergyPlusData &state)
    2520              :     {
    2521           10 :         if (this->lastOpMode == OpMode::None)
    2522            5 :             return; // this should only happen at the beginning of a simulation (at the start of warmup and the actual simulation)
    2523              :                     // so let things proceed with whatever the system wants to do
    2524              : 
    2525            5 :         if (this->opMode == OpMode::None) return; // always let it turn off
    2526              : 
    2527            4 :         if (this->opMode == this->lastOpMode) return; // always let it continue to operating in the same mode
    2528              : 
    2529            3 :         if (this->changeoverDelaySched == nullptr) return; // user not requesting any delays (no schedule entered) so let it do whatever is requested
    2530              : 
    2531            2 :         Real64 currentChangeoverDelay = this->changeoverDelaySched->getCurrentVal();
    2532            2 :         if (currentChangeoverDelay <= 0.0) return; // delay is zero so let it do whatever it requested
    2533              : 
    2534              :         // At this point, the radiant system is trying to switch modes from the previous time step, the user is requesting a delay in the changeover,
    2535              :         // and the requested delay is greater than zero.  Calculate what the current time is in hours from the start of the simulation
    2536            2 :         Real64 timeCurrent = 24.0 * float(state.dataGlobal->DayOfSim - 1) + float(state.dataGlobal->HourOfDay - 1) +
    2537            2 :                              float(state.dataGlobal->TimeStep - 1) / float(state.dataGlobal->TimeStepsInHour);
    2538            2 :         Real64 timeLast = 24.0 * float(this->lastDayOfSim - 1) + float(this->lastHourOfDay - 1) +
    2539            2 :                           float(this->lastTimeStep - 1) / float(state.dataGlobal->TimeStepsInHour);
    2540            2 :         Real64 actualTimeDifference = timeCurrent - timeLast;
    2541              : 
    2542              :         // If the time difference is not longer than the user delay, then the system should not switch modes and needs to be turned off.
    2543            2 :         if (actualTimeDifference <= currentChangeoverDelay) this->opMode = OpMode::None;
    2544              : 
    2545              :         // Note: if the time difference is greater than the user delay request, then go ahead and keep the operating mode needed (don't do anything).
    2546              :     }
    2547              : 
    2548           20 :     void SizeLowTempRadiantSystem(EnergyPlusData &state,
    2549              :                                   int const RadSysNum, // Index for the low temperature radiant system under consideration within the derived types
    2550              :                                   SystemType const systemType // Type of radiant system: hydronic, constant flow, or electric
    2551              :     )
    2552              :     {
    2553              : 
    2554              :         // SUBROUTINE INFORMATION:
    2555              :         //       AUTHOR         Fred Buhl
    2556              :         //       DATE WRITTEN   February 2002
    2557              :         //       MODIFIED       August 2013 Daeho Kang, add component sizing table entries
    2558              :         //                      August 2014 Bereket Nigusse, added scalable sizing
    2559              :         //                      March 2014 Daeho Kang, add constant flow system autosizing
    2560              : 
    2561              :         // PURPOSE OF THIS SUBROUTINE:
    2562              :         // This subroutine is for sizing low temperature radiant components for which flow rates
    2563              :         // and tube length or max electric power have not been specified in the input
    2564              : 
    2565              :         // METHODOLOGY EMPLOYED:
    2566              :         // Obtains flow rates from the zone sizing arrays and plant sizing data. Maximum electric
    2567              :         // power is set to the design heat load. Tube length is calculated by rule-of-thumb from
    2568              :         // the surface area.
    2569              : 
    2570              :         // Using/Aliasing
    2571              :         using namespace DataSizing;
    2572              :         using HVAC::AutoCalculateSizing;
    2573              :         using HVAC::CoolingCapacitySizing;
    2574              :         using HVAC::HeatingCapacitySizing;
    2575              : 
    2576              :         using PlantUtilities::MyPlantSizingIndex;
    2577              :         using PlantUtilities::RegisterPlantCompDesignFlow;
    2578              : 
    2579              :         // SUBROUTINE PARAMETER DEFINITIONS:
    2580           20 :         constexpr std::string_view RoutineName("SizeLowTempRadiantSystem");
    2581              : 
    2582              :         enum class OperatingMode
    2583              :         {
    2584              :             Invalid = -1,
    2585              :             OFF,
    2586              :             ClgHtg,
    2587              :             ClgOnly,
    2588              :             HtgOnly,
    2589              :             Num
    2590              :         };
    2591              : 
    2592              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    2593           20 :         int PltSizHeatNum(0);    // index of plant sizing object for 1st heating loop
    2594           20 :         int PltSizCoolNum(0);    // index of plant sizing object for 1st cooling loop
    2595              :         int SurfNum;             // surface index in radiant system data structure
    2596           20 :         bool ErrorsFound(false); // If errors detected in input
    2597              :         Real64 rho;
    2598              :         Real64 Cp;
    2599           20 :         bool IsAutoSize(false);              // Indicator to autosize
    2600           20 :         Real64 WaterVolFlowMaxHeatDes(0.0);  // Design hot water flow for reporting
    2601           20 :         Real64 WaterVolFlowMaxHeatUser(0.0); // User hard-sized hot water flow for
    2602           20 :         Real64 WaterVolFlowMaxCoolDes(0.0);  // Design chilled water flow for reporting
    2603           20 :         Real64 WaterVolFlowMaxCoolUser(0.0); // User hard-sized chilled water flow for reporting
    2604           20 :         Real64 TubeLengthDes(0.0);           // Design tube length for reporting
    2605           20 :         Real64 TubeLengthUser(0.0);          // User hard-sized tube length for reporting
    2606           20 :         std::string CompName;                // component name
    2607           20 :         std::string CompType;                // component type
    2608           20 :         std::string SizingString;            // input field sizing description (e.g., Nominal Capacity)
    2609              :         Real64 TempSize;                     // autosized value of coil input field
    2610              :         int FieldNum;                        // IDD numeric field number where input field description is found
    2611              :         bool PrintFlag;                      // TRUE when sizing information is reported in the eio file
    2612              :         int CapSizingMethod;        // capacity sizing methods (HeatingDesignCapacity, CapacityPerFloorArea, FractionOfAutosizedCoolingCapacity, and
    2613              :                                     // FractionOfAutosizedHeatingCapacity )
    2614              :         Real64 DesCoilLoad;         // design autosized or user specified capacity
    2615              :         Real64 WaterVolFlowMaxDes;  // Design water volume flow rate for reporting
    2616              :         Real64 WaterVolFlowMaxUser; // User hard-sized water volume flow rate for reporting
    2617              : 
    2618           20 :         DesCoilLoad = 0.0;
    2619           20 :         state.dataSize->DataScalableCapSizingON = false;
    2620           20 :         state.dataSize->DataFracOfAutosizedHeatingCapacity = 1.0;
    2621              : 
    2622           20 :         auto const &Zone = state.dataHeatBal->Zone;
    2623              : 
    2624           20 :         if (systemType == SystemType::Electric) {
    2625              : 
    2626            3 :             if (state.dataLowTempRadSys->ElecRadSys(RadSysNum).MaxElecPower == AutoSize) {
    2627            3 :                 IsAutoSize = true;
    2628              :             }
    2629              : 
    2630            3 :             if (state.dataSize->CurZoneEqNum > 0) {
    2631            3 :                 auto &zoneEqSizing = state.dataSize->ZoneEqSizing(state.dataSize->CurZoneEqNum);
    2632              : 
    2633            3 :                 CompType = "ZoneHVAC:LowTemperatureRadiant:Electric";
    2634            3 :                 CompName = state.dataLowTempRadSys->ElecRadSys(RadSysNum).Name;
    2635            3 :                 int SizingMethod = HeatingCapacitySizing;
    2636            3 :                 FieldNum = 1;
    2637            3 :                 PrintFlag = true;
    2638            3 :                 SizingString = state.dataLowTempRadSys->ElecRadSysNumericFields(RadSysNum).FieldNames(FieldNum) + " [W]";
    2639            3 :                 CapSizingMethod = state.dataLowTempRadSys->ElecRadSys(RadSysNum).HeatingCapMethod;
    2640            3 :                 zoneEqSizing.SizingMethod(SizingMethod) = CapSizingMethod;
    2641              : 
    2642            3 :                 if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) { // simulation continue
    2643            0 :                     if (CapSizingMethod == HeatingDesignCapacity && state.dataLowTempRadSys->ElecRadSys(RadSysNum).ScaledHeatingCapacity > 0.0) {
    2644            0 :                         TempSize = state.dataLowTempRadSys->ElecRadSys(RadSysNum).ScaledHeatingCapacity;
    2645            0 :                         bool errorsFound = false;
    2646            0 :                         HeatingCapacitySizer sizerHeatingCapacity;
    2647            0 :                         sizerHeatingCapacity.overrideSizingString(SizingString);
    2648            0 :                         sizerHeatingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
    2649            0 :                         DesCoilLoad = sizerHeatingCapacity.size(state, TempSize, errorsFound);
    2650            0 :                     } else if (CapSizingMethod == CapacityPerFloorArea) {
    2651            0 :                         state.dataSize->DataScalableCapSizingON = true;
    2652            0 :                         TempSize = state.dataLowTempRadSys->ElecRadSys(RadSysNum).ScaledHeatingCapacity *
    2653            0 :                                    Zone(state.dataLowTempRadSys->ElecRadSys(RadSysNum).ZonePtr).FloorArea;
    2654            0 :                         bool errorsFound = false;
    2655            0 :                         HeatingCapacitySizer sizerHeatingCapacity;
    2656            0 :                         sizerHeatingCapacity.overrideSizingString(SizingString);
    2657            0 :                         sizerHeatingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
    2658            0 :                         DesCoilLoad = sizerHeatingCapacity.size(state, TempSize, errorsFound);
    2659            0 :                         state.dataSize->DataScalableCapSizingON = false;
    2660            0 :                         state.dataLowTempRadSys->ElecRadSys(RadSysNum).MaxElecPower = TempSize;
    2661            0 :                     } else if (CapSizingMethod == FractionOfAutosizedHeatingCapacity) {
    2662            0 :                         ShowSevereError(state,
    2663            0 :                                         format("{}: auto-sizing cannot be done for {} = {}\".",
    2664              :                                                RoutineName,
    2665              :                                                CompType,
    2666            0 :                                                state.dataLowTempRadSys->ElecRadSys(RadSysNum).Name));
    2667            0 :                         ShowContinueError(state,
    2668              :                                           "The \"SimulationControl\" object must have the field \"Do Zone Sizing Calculation\" set to Yes when the "
    2669              :                                           "Heating Design Capacity Method = \"FractionOfAutosizedHeatingCapacity\".");
    2670            0 :                         ErrorsFound = true;
    2671              :                     }
    2672              :                 } else {
    2673            3 :                     if (CapSizingMethod == HeatingDesignCapacity || CapSizingMethod == CapacityPerFloorArea ||
    2674              :                         CapSizingMethod == FractionOfAutosizedHeatingCapacity) {
    2675            3 :                         if (CapSizingMethod == HeatingDesignCapacity) {
    2676            1 :                             if (state.dataSize->ZoneSizingRunDone) {
    2677            1 :                                 CheckZoneSizing(state, CompType, CompName);
    2678            2 :                                 state.dataSize->DataConstantUsedForSizing =
    2679            1 :                                     state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).NonAirSysDesHeatLoad;
    2680            1 :                                 state.dataSize->DataFractionUsedForSizing = 1.0;
    2681              :                             }
    2682            1 :                             if (state.dataLowTempRadSys->ElecRadSys(RadSysNum).ScaledHeatingCapacity == AutoSize) {
    2683            1 :                                 TempSize = AutoSize;
    2684              :                             } else {
    2685            0 :                                 TempSize = state.dataLowTempRadSys->ElecRadSys(RadSysNum).ScaledHeatingCapacity;
    2686              :                             }
    2687            2 :                         } else if (CapSizingMethod == CapacityPerFloorArea) {
    2688            1 :                             if (state.dataSize->ZoneSizingRunDone) {
    2689            1 :                                 CheckZoneSizing(state, CompType, CompName);
    2690            1 :                                 zoneEqSizing.HeatingCapacity = true;
    2691            1 :                                 zoneEqSizing.DesHeatingLoad = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).NonAirSysDesHeatLoad;
    2692              :                             }
    2693            1 :                             TempSize = state.dataLowTempRadSys->ElecRadSys(RadSysNum).ScaledHeatingCapacity *
    2694            1 :                                        Zone(state.dataLowTempRadSys->ElecRadSys(RadSysNum).ZonePtr).FloorArea;
    2695            1 :                             state.dataSize->DataScalableCapSizingON = true;
    2696              : 
    2697            1 :                         } else if (CapSizingMethod == FractionOfAutosizedHeatingCapacity) {
    2698            1 :                             CheckZoneSizing(state, CompType, CompName);
    2699            1 :                             zoneEqSizing.HeatingCapacity = true;
    2700            1 :                             zoneEqSizing.DesHeatingLoad = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).NonAirSysDesHeatLoad;
    2701            1 :                             TempSize = zoneEqSizing.DesHeatingLoad * state.dataLowTempRadSys->ElecRadSys(RadSysNum).ScaledHeatingCapacity;
    2702            1 :                             state.dataSize->DataScalableCapSizingON = true;
    2703              :                         } else {
    2704            0 :                             TempSize = state.dataLowTempRadSys->ElecRadSys(RadSysNum).ScaledHeatingCapacity;
    2705              :                         }
    2706            3 :                         HeatingCapacitySizer sizerHeatingCapacity;
    2707            3 :                         sizerHeatingCapacity.overrideSizingString(SizingString);
    2708            3 :                         sizerHeatingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
    2709            3 :                         state.dataLowTempRadSys->ElecRadSys(RadSysNum).MaxElecPower = sizerHeatingCapacity.size(state, TempSize, ErrorsFound);
    2710            3 :                         state.dataSize->DataConstantUsedForSizing = 0.0;
    2711            3 :                         state.dataSize->DataFractionUsedForSizing = 0.0;
    2712            3 :                         state.dataSize->DataScalableCapSizingON = false;
    2713            3 :                     }
    2714              :                 }
    2715              :             }
    2716              : 
    2717           17 :         } else if (systemType == SystemType::Hydronic) {
    2718              : 
    2719            7 :             CompType = "ZoneHVAC:LowTemperatureRadiant:VariableFlow";
    2720            7 :             CompName = state.dataLowTempRadSys->HydrRadSys(RadSysNum).Name;
    2721              : 
    2722            7 :             IsAutoSize = false;
    2723            7 :             if (state.dataLowTempRadSys->HydrRadSys(RadSysNum).ScaledHeatingCapacity == AutoSize) {
    2724            2 :                 IsAutoSize = true;
    2725              :             }
    2726              : 
    2727            7 :             if (state.dataSize->CurZoneEqNum > 0) {
    2728            7 :                 auto &zoneEqSizing = state.dataSize->ZoneEqSizing(state.dataSize->CurZoneEqNum);
    2729              : 
    2730            7 :                 int SizingMethod = HeatingCapacitySizing;
    2731            7 :                 FieldNum = 2;
    2732            7 :                 PrintFlag = true;
    2733            7 :                 SizingString = state.dataLowTempRadSys->HydronicRadiantSysNumericFields(RadSysNum).FieldNames(FieldNum) + " [W]";
    2734            7 :                 CapSizingMethod = state.dataLowTempRadSys->HydrRadSys(RadSysNum).HeatingCapMethod;
    2735            7 :                 zoneEqSizing.SizingMethod(SizingMethod) = CapSizingMethod;
    2736              : 
    2737            7 :                 if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) { // simulation continue
    2738            0 :                     if (CapSizingMethod == HeatingDesignCapacity && state.dataLowTempRadSys->HydrRadSys(RadSysNum).ScaledHeatingCapacity > 0.0) {
    2739            0 :                         TempSize = state.dataLowTempRadSys->HydrRadSys(RadSysNum).ScaledHeatingCapacity;
    2740            0 :                         bool errorsFound = false;
    2741            0 :                         HeatingCapacitySizer sizerHeatingCapacity;
    2742            0 :                         sizerHeatingCapacity.overrideSizingString(SizingString);
    2743            0 :                         sizerHeatingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
    2744            0 :                         DesCoilLoad = sizerHeatingCapacity.size(state, TempSize, errorsFound);
    2745            0 :                     } else if (CapSizingMethod == CapacityPerFloorArea) {
    2746            0 :                         state.dataSize->DataScalableCapSizingON = true;
    2747            0 :                         TempSize = state.dataLowTempRadSys->HydrRadSys(RadSysNum).ScaledHeatingCapacity *
    2748            0 :                                    Zone(state.dataLowTempRadSys->HydrRadSys(RadSysNum).ZonePtr).FloorArea;
    2749            0 :                         HeatingCapacitySizer sizerHeatingCapacity;
    2750            0 :                         sizerHeatingCapacity.overrideSizingString(SizingString);
    2751            0 :                         sizerHeatingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
    2752            0 :                         DesCoilLoad = sizerHeatingCapacity.size(state, TempSize, ErrorsFound);
    2753            0 :                         state.dataSize->DataScalableCapSizingON = false;
    2754            0 :                     } else if (CapSizingMethod == FractionOfAutosizedHeatingCapacity) {
    2755            0 :                         if (state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterVolFlowMaxHeat == AutoSize) {
    2756            0 :                             ShowSevereError(state,
    2757            0 :                                             format("{}: auto-sizing cannot be done for {} = {}\".",
    2758              :                                                    RoutineName,
    2759              :                                                    CompType,
    2760            0 :                                                    state.dataLowTempRadSys->HydrRadSys(RadSysNum).Name));
    2761            0 :                             ShowContinueError(state,
    2762              :                                               "The \"SimulationControl\" object must have the field \"Do Zone Sizing Calculation\" set to Yes when "
    2763              :                                               "the Heating Design Capacity Method = \"FractionOfAutosizedHeatingCapacity\".");
    2764            0 :                             ErrorsFound = true;
    2765              :                         }
    2766              :                     }
    2767              :                 } else { // Autosize or hard-size with sizing run
    2768            7 :                     if (CapSizingMethod == HeatingDesignCapacity || CapSizingMethod == CapacityPerFloorArea ||
    2769              :                         CapSizingMethod == FractionOfAutosizedHeatingCapacity) {
    2770            7 :                         if (CapSizingMethod == HeatingDesignCapacity) {
    2771            2 :                             if (state.dataSize->ZoneSizingRunDone) {
    2772            2 :                                 CheckZoneSizing(state, CompType, CompName);
    2773            4 :                                 state.dataSize->DataConstantUsedForSizing =
    2774            2 :                                     state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).NonAirSysDesHeatLoad;
    2775            2 :                                 state.dataSize->DataFractionUsedForSizing = 1.0;
    2776              :                             }
    2777            2 :                             if (state.dataLowTempRadSys->HydrRadSys(RadSysNum).ScaledHeatingCapacity == AutoSize) {
    2778            2 :                                 TempSize = AutoSize;
    2779              :                             } else {
    2780            0 :                                 TempSize = state.dataLowTempRadSys->HydrRadSys(RadSysNum).ScaledHeatingCapacity;
    2781              :                             }
    2782            5 :                         } else if (CapSizingMethod == CapacityPerFloorArea) {
    2783            2 :                             if (state.dataSize->ZoneSizingRunDone) {
    2784            2 :                                 CheckZoneSizing(state, CompType, CompName);
    2785            2 :                                 zoneEqSizing.HeatingCapacity = true;
    2786            2 :                                 zoneEqSizing.DesHeatingLoad = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).NonAirSysDesHeatLoad;
    2787              :                             }
    2788            2 :                             TempSize = state.dataLowTempRadSys->HydrRadSys(RadSysNum).ScaledHeatingCapacity *
    2789            2 :                                        Zone(state.dataLowTempRadSys->HydrRadSys(RadSysNum).ZonePtr).FloorArea;
    2790            2 :                             state.dataSize->DataScalableCapSizingON = true;
    2791            3 :                         } else if (CapSizingMethod == FractionOfAutosizedHeatingCapacity) {
    2792            3 :                             CheckZoneSizing(state, CompType, CompName);
    2793            3 :                             zoneEqSizing.HeatingCapacity = true;
    2794            3 :                             zoneEqSizing.DesHeatingLoad = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).NonAirSysDesHeatLoad;
    2795            3 :                             TempSize = zoneEqSizing.DesHeatingLoad * state.dataLowTempRadSys->HydrRadSys(RadSysNum).ScaledHeatingCapacity;
    2796            3 :                             state.dataSize->DataScalableCapSizingON = true;
    2797              :                         } else {
    2798            0 :                             TempSize = state.dataLowTempRadSys->HydrRadSys(RadSysNum).ScaledHeatingCapacity;
    2799              :                         }
    2800            7 :                         HeatingCapacitySizer sizerHeatingCapacity;
    2801            7 :                         sizerHeatingCapacity.overrideSizingString(SizingString);
    2802            7 :                         sizerHeatingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
    2803            7 :                         DesCoilLoad = sizerHeatingCapacity.size(state, TempSize, ErrorsFound);
    2804            7 :                         state.dataSize->DataConstantUsedForSizing = 0.0;
    2805            7 :                         state.dataSize->DataFractionUsedForSizing = 0.0;
    2806            7 :                         state.dataSize->DataScalableCapSizingON = false;
    2807            7 :                     } else {
    2808            0 :                         DesCoilLoad = 0.0;
    2809              :                     }
    2810              :                 }
    2811              :                 // finally heating capacity is saved in this variable
    2812            7 :                 state.dataLowTempRadSys->HydrRadSys(RadSysNum).ScaledHeatingCapacity = DesCoilLoad;
    2813              :             }
    2814              : 
    2815            7 :             IsAutoSize = false;
    2816            7 :             if (state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterVolFlowMaxHeat == AutoSize) {
    2817            4 :                 IsAutoSize = true;
    2818              :             }
    2819              : 
    2820            7 :             if (state.dataSize->CurZoneEqNum > 0) {
    2821            7 :                 if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) { // simulation continue
    2822            0 :                     if (state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterVolFlowMaxHeat > 0.0) {
    2823            0 :                         BaseSizer::reportSizerOutput(state,
    2824              :                                                      CompType,
    2825            0 :                                                      state.dataLowTempRadSys->HydrRadSys(RadSysNum).Name,
    2826              :                                                      "User-Specified Maximum Hot Water Flow [m3/s]",
    2827            0 :                                                      state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterVolFlowMaxHeat);
    2828              :                     }
    2829              :                 } else { // Autosize or hard-size with sizing run
    2830           14 :                     if (state.dataLowTempRadSys->HydrRadSys(RadSysNum).HotWaterInNode > 0 &&
    2831            7 :                         state.dataLowTempRadSys->HydrRadSys(RadSysNum).HotWaterOutNode > 0) {
    2832            7 :                         PltSizHeatNum = MyPlantSizingIndex(state,
    2833              :                                                            CompType,
    2834            7 :                                                            state.dataLowTempRadSys->HydrRadSys(RadSysNum).Name,
    2835            7 :                                                            state.dataLowTempRadSys->HydrRadSys(RadSysNum).HotWaterInNode,
    2836            7 :                                                            state.dataLowTempRadSys->HydrRadSys(RadSysNum).HotWaterOutNode,
    2837              :                                                            ErrorsFound);
    2838            7 :                         if (PltSizHeatNum > 0) {
    2839            7 :                             if (DesCoilLoad >= SmallLoad) {
    2840            7 :                                 rho = state.dataPlnt->PlantLoop(state.dataLowTempRadSys->HydrRadSys(RadSysNum).HWPlantLoc.loopNum)
    2841            7 :                                           .glycol->getDensity(state, Constant::HWInitConvTemp, RoutineName);
    2842            7 :                                 Cp = state.dataPlnt->PlantLoop(state.dataLowTempRadSys->HydrRadSys(RadSysNum).HWPlantLoc.loopNum)
    2843            7 :                                          .glycol->getSpecificHeat(state, Constant::HWInitConvTemp, RoutineName);
    2844            7 :                                 WaterVolFlowMaxHeatDes = DesCoilLoad / (state.dataSize->PlantSizData(PltSizHeatNum).DeltaT * Cp * rho);
    2845              :                             } else {
    2846            0 :                                 WaterVolFlowMaxHeatDes = 0.0;
    2847              :                             }
    2848              :                         } else {
    2849            0 :                             ShowSevereError(state, "Autosizing of water flow requires a heating loop Sizing:Plant object");
    2850            0 :                             ShowContinueError(state,
    2851            0 :                                               format("Occurs in ZoneHVAC:LowTemperatureRadiant:VariableFlow Object={}",
    2852            0 :                                                      state.dataLowTempRadSys->HydrRadSys(RadSysNum).Name));
    2853            0 :                             ErrorsFound = true;
    2854              :                         }
    2855              :                     }
    2856              : 
    2857            7 :                     if (IsAutoSize) {
    2858            4 :                         state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterVolFlowMaxHeat = WaterVolFlowMaxHeatDes;
    2859            8 :                         BaseSizer::reportSizerOutput(state,
    2860              :                                                      CompType,
    2861            4 :                                                      state.dataLowTempRadSys->HydrRadSys(RadSysNum).Name,
    2862              :                                                      "Design Size Maximum Hot Water Flow [m3/s]",
    2863              :                                                      WaterVolFlowMaxHeatDes);
    2864              :                     } else { // hard-size with sizing data
    2865            3 :                         if (state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterVolFlowMaxHeat > 0.0 && WaterVolFlowMaxHeatDes > 0.0) {
    2866            0 :                             WaterVolFlowMaxHeatUser = state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterVolFlowMaxHeat;
    2867            0 :                             BaseSizer::reportSizerOutput(state,
    2868              :                                                          CompType,
    2869            0 :                                                          state.dataLowTempRadSys->HydrRadSys(RadSysNum).Name,
    2870              :                                                          "Design Size Maximum Hot Water Flow [m3/s]",
    2871              :                                                          WaterVolFlowMaxHeatDes,
    2872              :                                                          "User-Specified Maximum Hot Water Flow [m3/s]",
    2873              :                                                          WaterVolFlowMaxHeatUser);
    2874            0 :                             if (state.dataGlobal->DisplayExtraWarnings) {
    2875            0 :                                 if ((std::abs(WaterVolFlowMaxHeatDes - WaterVolFlowMaxHeatUser) / WaterVolFlowMaxHeatUser) >
    2876            0 :                                     state.dataSize->AutoVsHardSizingThreshold) {
    2877            0 :                                     ShowMessage(state,
    2878            0 :                                                 format("SizeLowTempRadiantSystem: Potential issue with equipment sizing for "
    2879              :                                                        "ZoneHVAC:LowTemperatureRadiant:VariableFlow = \"{}\".",
    2880            0 :                                                        state.dataLowTempRadSys->HydrRadSys(RadSysNum).Name));
    2881            0 :                                     ShowContinueError(state,
    2882            0 :                                                       format("User-Specified Maximum Hot Water Flow of {:.5R} [m3/s]", WaterVolFlowMaxHeatUser));
    2883            0 :                                     ShowContinueError(
    2884            0 :                                         state, format("differs from Design Size Maximum Hot Water Flow of {:.5R} [m3/s]", WaterVolFlowMaxHeatDes));
    2885            0 :                                     ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
    2886            0 :                                     ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
    2887              :                                 }
    2888              :                             }
    2889              :                         }
    2890              :                     }
    2891              :                 }
    2892              :             }
    2893              : 
    2894            7 :             IsAutoSize = false;
    2895            7 :             if (state.dataLowTempRadSys->HydrRadSys(RadSysNum).ScaledCoolingCapacity == AutoSize) {
    2896            2 :                 IsAutoSize = true;
    2897              :             }
    2898              : 
    2899            7 :             if (state.dataSize->CurZoneEqNum > 0) {
    2900            7 :                 auto &zoneEqSizing = state.dataSize->ZoneEqSizing(state.dataSize->CurZoneEqNum);
    2901              : 
    2902            7 :                 int SizingMethod = CoolingCapacitySizing;
    2903            7 :                 FieldNum = 4;
    2904            7 :                 PrintFlag = true;
    2905            7 :                 SizingString = state.dataLowTempRadSys->HydronicRadiantSysNumericFields(RadSysNum).FieldNames(FieldNum) + " [W]";
    2906            7 :                 CapSizingMethod = state.dataLowTempRadSys->HydrRadSys(RadSysNum).CoolingCapMethod;
    2907            7 :                 zoneEqSizing.SizingMethod(SizingMethod) = CapSizingMethod;
    2908              : 
    2909            7 :                 if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) { // simulation continue
    2910            0 :                     if (CapSizingMethod == CoolingDesignCapacity && state.dataLowTempRadSys->HydrRadSys(RadSysNum).ScaledCoolingCapacity > 0.0) {
    2911            0 :                         TempSize = state.dataLowTempRadSys->HydrRadSys(RadSysNum).ScaledCoolingCapacity;
    2912            0 :                         CoolingCapacitySizer sizerCoolingCapacity;
    2913            0 :                         sizerCoolingCapacity.overrideSizingString(SizingString);
    2914            0 :                         sizerCoolingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
    2915            0 :                         DesCoilLoad = sizerCoolingCapacity.size(state, TempSize, ErrorsFound);
    2916            0 :                     } else if (CapSizingMethod == CapacityPerFloorArea) {
    2917            0 :                         state.dataSize->DataScalableCapSizingON = true;
    2918            0 :                         TempSize = state.dataLowTempRadSys->HydrRadSys(RadSysNum).ScaledCoolingCapacity *
    2919            0 :                                    Zone(state.dataLowTempRadSys->HydrRadSys(RadSysNum).ZonePtr).FloorArea;
    2920            0 :                         CoolingCapacitySizer sizerCoolingCapacity;
    2921            0 :                         sizerCoolingCapacity.overrideSizingString(SizingString);
    2922            0 :                         sizerCoolingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
    2923            0 :                         DesCoilLoad = sizerCoolingCapacity.size(state, TempSize, ErrorsFound);
    2924            0 :                         state.dataSize->DataScalableCapSizingON = false;
    2925            0 :                     } else if (CapSizingMethod == FractionOfAutosizedCoolingCapacity) {
    2926            0 :                         if (state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterVolFlowMaxCool == AutoSize) {
    2927            0 :                             ShowSevereError(state,
    2928            0 :                                             format("{}: auto-sizing cannot be done for {} = {}\".",
    2929              :                                                    RoutineName,
    2930              :                                                    CompType,
    2931            0 :                                                    state.dataLowTempRadSys->HydrRadSys(RadSysNum).Name));
    2932            0 :                             ShowContinueError(state,
    2933              :                                               "The \"SimulationControl\" object must have the field \"Do Zone Sizing Calculation\" set to Yes when "
    2934              :                                               "the Cooling Design Capacity Method = \"FractionOfAutosizedCoolingCapacity\".");
    2935            0 :                             ErrorsFound = true;
    2936              :                         }
    2937              :                     }
    2938              :                 } else { // Autosize or hard-size with sizing run
    2939            7 :                     if (CapSizingMethod == CoolingDesignCapacity || CapSizingMethod == CapacityPerFloorArea ||
    2940              :                         CapSizingMethod == FractionOfAutosizedCoolingCapacity) {
    2941            7 :                         if (CapSizingMethod == CoolingDesignCapacity) {
    2942            2 :                             if (state.dataSize->ZoneSizingRunDone) {
    2943            2 :                                 CheckZoneSizing(state, CompType, CompName);
    2944            4 :                                 state.dataSize->DataConstantUsedForSizing =
    2945            2 :                                     state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).NonAirSysDesCoolLoad;
    2946            2 :                                 state.dataSize->DataFractionUsedForSizing = 1.0;
    2947              :                             }
    2948            2 :                             if (state.dataLowTempRadSys->HydrRadSys(RadSysNum).ScaledCoolingCapacity == AutoSize) {
    2949            2 :                                 TempSize = AutoSize;
    2950              :                             } else {
    2951            0 :                                 TempSize = state.dataLowTempRadSys->HydrRadSys(RadSysNum).ScaledCoolingCapacity;
    2952              :                             }
    2953            5 :                         } else if (CapSizingMethod == CapacityPerFloorArea) {
    2954            2 :                             if (state.dataSize->ZoneSizingRunDone) {
    2955            2 :                                 CheckZoneSizing(state, CompType, CompName);
    2956            2 :                                 zoneEqSizing.CoolingCapacity = true;
    2957            2 :                                 zoneEqSizing.DesCoolingLoad = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).NonAirSysDesCoolLoad;
    2958              :                             }
    2959            2 :                             TempSize = state.dataLowTempRadSys->HydrRadSys(RadSysNum).ScaledCoolingCapacity *
    2960            2 :                                        Zone(state.dataLowTempRadSys->HydrRadSys(RadSysNum).ZonePtr).FloorArea;
    2961            2 :                             state.dataSize->DataScalableCapSizingON = true;
    2962            3 :                         } else if (CapSizingMethod == FractionOfAutosizedCoolingCapacity) {
    2963            3 :                             CheckZoneSizing(state, CompType, CompName);
    2964            3 :                             zoneEqSizing.CoolingCapacity = true;
    2965            3 :                             zoneEqSizing.DesCoolingLoad = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).NonAirSysDesCoolLoad;
    2966            3 :                             TempSize = zoneEqSizing.DesCoolingLoad * state.dataLowTempRadSys->HydrRadSys(RadSysNum).ScaledCoolingCapacity;
    2967            3 :                             state.dataSize->DataScalableCapSizingON = true;
    2968              : 
    2969              :                         } else {
    2970            0 :                             TempSize = state.dataLowTempRadSys->HydrRadSys(RadSysNum).ScaledCoolingCapacity;
    2971              :                         }
    2972            7 :                         CoolingCapacitySizer sizerCoolingCapacity;
    2973            7 :                         sizerCoolingCapacity.overrideSizingString(SizingString);
    2974            7 :                         sizerCoolingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
    2975            7 :                         DesCoilLoad = sizerCoolingCapacity.size(state, TempSize, ErrorsFound);
    2976            7 :                         state.dataSize->DataConstantUsedForSizing = 0.0;
    2977            7 :                         state.dataSize->DataFractionUsedForSizing = 0.0;
    2978            7 :                         state.dataSize->DataScalableCapSizingON = false;
    2979            7 :                     } else {
    2980            0 :                         DesCoilLoad = 0.0;
    2981              :                     }
    2982              :                 }
    2983              :                 // finally cooling capacity is saved in this variable
    2984            7 :                 state.dataLowTempRadSys->HydrRadSys(RadSysNum).ScaledCoolingCapacity = DesCoilLoad;
    2985              :             }
    2986              : 
    2987            7 :             IsAutoSize = false;
    2988            7 :             if (state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterVolFlowMaxCool == AutoSize) {
    2989            4 :                 IsAutoSize = true;
    2990              :             }
    2991            7 :             if (state.dataSize->CurZoneEqNum > 0) {
    2992            7 :                 if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) { // simulation continue
    2993            0 :                     if (state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterVolFlowMaxCool > 0.0) {
    2994            0 :                         BaseSizer::reportSizerOutput(state,
    2995              :                                                      CompType,
    2996            0 :                                                      state.dataLowTempRadSys->HydrRadSys(RadSysNum).Name,
    2997              :                                                      "User-Specified Maximum Cold Water Flow [m3/s]",
    2998            0 :                                                      state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterVolFlowMaxCool);
    2999              :                     }
    3000              :                 } else { // Autosize or hard-size with sizing run
    3001           14 :                     if (state.dataLowTempRadSys->HydrRadSys(RadSysNum).ColdWaterInNode > 0 &&
    3002            7 :                         state.dataLowTempRadSys->HydrRadSys(RadSysNum).ColdWaterOutNode > 0) {
    3003            7 :                         PltSizCoolNum = MyPlantSizingIndex(state,
    3004              :                                                            CompType,
    3005            7 :                                                            state.dataLowTempRadSys->HydrRadSys(RadSysNum).Name,
    3006            7 :                                                            state.dataLowTempRadSys->HydrRadSys(RadSysNum).ColdWaterInNode,
    3007            7 :                                                            state.dataLowTempRadSys->HydrRadSys(RadSysNum).ColdWaterOutNode,
    3008              :                                                            ErrorsFound);
    3009            7 :                         if (PltSizCoolNum > 0) {
    3010            7 :                             if (DesCoilLoad >= SmallLoad) {
    3011            7 :                                 rho = state.dataPlnt->PlantLoop(state.dataLowTempRadSys->HydrRadSys(RadSysNum).CWPlantLoc.loopNum)
    3012            7 :                                           .glycol->getDensity(state, Constant::CWInitConvTemp, RoutineName);
    3013            7 :                                 Cp = state.dataPlnt->PlantLoop(state.dataLowTempRadSys->HydrRadSys(RadSysNum).CWPlantLoc.loopNum)
    3014            7 :                                          .glycol->getSpecificHeat(state, Constant::CWInitConvTemp, RoutineName);
    3015            7 :                                 WaterVolFlowMaxCoolDes = DesCoilLoad / (state.dataSize->PlantSizData(PltSizCoolNum).DeltaT * Cp * rho);
    3016              :                             } else {
    3017            0 :                                 WaterVolFlowMaxCoolDes = 0.0;
    3018              :                             }
    3019              :                         } else {
    3020            0 :                             ShowSevereError(state, "Autosizing of water flow requires a cooling loop Sizing:Plant object");
    3021            0 :                             ShowContinueError(state,
    3022            0 :                                               format("Occurs in ZoneHVAC:LowTemperatureRadiant:VariableFlow Object={}",
    3023            0 :                                                      state.dataLowTempRadSys->HydrRadSys(RadSysNum).Name));
    3024            0 :                             ErrorsFound = true;
    3025              :                         }
    3026              :                     }
    3027              : 
    3028            7 :                     if (IsAutoSize) {
    3029            4 :                         state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterVolFlowMaxCool = WaterVolFlowMaxCoolDes;
    3030            8 :                         BaseSizer::reportSizerOutput(state,
    3031              :                                                      CompType,
    3032            4 :                                                      state.dataLowTempRadSys->HydrRadSys(RadSysNum).Name,
    3033              :                                                      "Design Size Maximum Cold Water Flow [m3/s]",
    3034              :                                                      WaterVolFlowMaxCoolDes);
    3035              :                     } else { // hard-size with sizing data
    3036            3 :                         if (state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterVolFlowMaxCool > 0.0 && WaterVolFlowMaxCoolDes > 0.0) {
    3037            0 :                             WaterVolFlowMaxCoolUser = state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterVolFlowMaxCool;
    3038            0 :                             BaseSizer::reportSizerOutput(state,
    3039              :                                                          CompType,
    3040            0 :                                                          state.dataLowTempRadSys->HydrRadSys(RadSysNum).Name,
    3041              :                                                          "Design Size Maximum Cold Water Flow [m3/s]",
    3042              :                                                          WaterVolFlowMaxCoolDes,
    3043              :                                                          "User-Specified Maximum Cold Water Flow [m3/s]",
    3044              :                                                          WaterVolFlowMaxCoolUser);
    3045            0 :                             if (state.dataGlobal->DisplayExtraWarnings) {
    3046            0 :                                 if ((std::abs(WaterVolFlowMaxCoolDes - WaterVolFlowMaxCoolUser) / WaterVolFlowMaxCoolUser) >
    3047            0 :                                     state.dataSize->AutoVsHardSizingThreshold) {
    3048            0 :                                     ShowMessage(state,
    3049            0 :                                                 format("SizeLowTempRadiantSystem: Potential issue with equipment sizing for "
    3050              :                                                        "ZoneHVAC:LowTemperatureRadiant:VariableFlow = \"{}\".",
    3051            0 :                                                        state.dataLowTempRadSys->HydrRadSys(RadSysNum).Name));
    3052            0 :                                     ShowContinueError(state,
    3053            0 :                                                       format("User-Specified Maximum Cool Water Flow of {:.5R} [m3/s]", WaterVolFlowMaxCoolUser));
    3054            0 :                                     ShowContinueError(
    3055            0 :                                         state, format("differs from Design Size Maximum Cool Water Flow of {:.5R} [m3/s]", WaterVolFlowMaxCoolDes));
    3056            0 :                                     ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
    3057            0 :                                     ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
    3058              :                                 }
    3059              :                             }
    3060              :                         }
    3061              :                     }
    3062              :                 }
    3063              :             }
    3064              : 
    3065            7 :             IsAutoSize = false;
    3066            7 :             if (state.dataLowTempRadSys->HydrRadSys(RadSysNum).TubeLength == AutoSize) {
    3067            2 :                 IsAutoSize = true;
    3068              :             }
    3069            7 :             if (state.dataSize->CurZoneEqNum > 0) {
    3070            7 :                 if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) { // simulation continue
    3071            0 :                     if (state.dataLowTempRadSys->HydrRadSys(RadSysNum).TubeLength > 0.0) {
    3072            0 :                         BaseSizer::reportSizerOutput(state,
    3073              :                                                      CompType,
    3074            0 :                                                      state.dataLowTempRadSys->HydrRadSys(RadSysNum).Name,
    3075              :                                                      "User-Specified Hydronic Tubing Length [m]",
    3076            0 :                                                      state.dataLowTempRadSys->HydrRadSys(RadSysNum).TubeLength);
    3077              :                     }
    3078              :                 } else { // Autosize or hard-size with sizing run
    3079              :                     // CheckZoneSizing is not required here because the tube length calculation is not dependent on zone sizing calculation results
    3080            7 :                     TubeLengthDes = state.dataLowTempRadSys->HydrRadSys(RadSysNum).sizeRadiantSystemTubeLength(state);
    3081            7 :                     if (IsAutoSize) {
    3082            2 :                         state.dataLowTempRadSys->HydrRadSys(RadSysNum).TubeLength = TubeLengthDes;
    3083            4 :                         BaseSizer::reportSizerOutput(state,
    3084              :                                                      CompType,
    3085            2 :                                                      state.dataLowTempRadSys->HydrRadSys(RadSysNum).Name,
    3086              :                                                      "Design Size Hydronic Tubing Length [m]",
    3087              :                                                      TubeLengthDes);
    3088              :                     } else { // hard-size with sizing data
    3089            5 :                         if (state.dataLowTempRadSys->HydrRadSys(RadSysNum).TubeLength > 0.0 && TubeLengthDes > 0.0) {
    3090            2 :                             TubeLengthUser = state.dataLowTempRadSys->HydrRadSys(RadSysNum).TubeLength;
    3091            4 :                             BaseSizer::reportSizerOutput(state,
    3092              :                                                          CompType,
    3093            2 :                                                          state.dataLowTempRadSys->HydrRadSys(RadSysNum).Name,
    3094              :                                                          "Design Size Hydronic Tubing Length [m]",
    3095              :                                                          TubeLengthDes,
    3096              :                                                          "User-Specified Hydronic Tubing Length [m]",
    3097              :                                                          TubeLengthUser);
    3098            2 :                             if (state.dataGlobal->DisplayExtraWarnings) {
    3099            0 :                                 if ((std::abs(TubeLengthDes - TubeLengthUser) / TubeLengthUser) > state.dataSize->AutoVsHardSizingThreshold) {
    3100            0 :                                     ShowMessage(state,
    3101            0 :                                                 format("SizeLowTempRadiantSystem: Potential issue with equipment sizing for "
    3102              :                                                        "ZoneHVAC:LowTemperatureRadiant:VariableFlow = \"{}\".",
    3103            0 :                                                        state.dataLowTempRadSys->HydrRadSys(RadSysNum).Name));
    3104            0 :                                     ShowContinueError(state, format("User-Specified Hydronic Tubing Length of {:.5R} [m]", TubeLengthUser));
    3105            0 :                                     ShowContinueError(state, format("differs from Design Size Hydronic Tubing Length of {:.5R} [m]", TubeLengthDes));
    3106            0 :                                     ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
    3107            0 :                                     ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
    3108              :                                 }
    3109              :                             }
    3110              :                         }
    3111              :                     }
    3112              :                 }
    3113              :             }
    3114              : 
    3115           11 :             for (SurfNum = 1; SurfNum <= state.dataLowTempRadSys->HydrRadSys(RadSysNum).NumOfSurfaces; ++SurfNum) {
    3116            4 :                 if (state.dataLowTempRadSys->HydrRadSys(RadSysNum).NumCircCalcMethod == CircuitCalc::CalculateFromLength) {
    3117            0 :                     state.dataLowTempRadSys->HydrRadSys(RadSysNum).NumCircuits(SurfNum) =
    3118            0 :                         (state.dataLowTempRadSys->HydrRadSys(RadSysNum).SurfaceFrac(SurfNum) *
    3119            0 :                          state.dataLowTempRadSys->HydrRadSys(RadSysNum).TubeLength) /
    3120            0 :                         state.dataLowTempRadSys->HydrRadSys(RadSysNum).CircLength;
    3121            0 :                     state.dataLowTempRadSys->HydrRadSys(RadSysNum).NumCircuits(SurfNum) =
    3122            0 :                         max(state.dataLowTempRadSys->HydrRadSys(RadSysNum).NumCircuits(SurfNum), 1.0);
    3123              :                 } else {
    3124            4 :                     state.dataLowTempRadSys->HydrRadSys(RadSysNum).NumCircuits(SurfNum) = 1.0;
    3125              :                 }
    3126              :             }
    3127              : 
    3128           14 :             RegisterPlantCompDesignFlow(state,
    3129            7 :                                         state.dataLowTempRadSys->HydrRadSys(RadSysNum).HotWaterInNode,
    3130            7 :                                         state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterVolFlowMaxHeat);
    3131           14 :             RegisterPlantCompDesignFlow(state,
    3132            7 :                                         state.dataLowTempRadSys->HydrRadSys(RadSysNum).ColdWaterInNode,
    3133            7 :                                         state.dataLowTempRadSys->HydrRadSys(RadSysNum).WaterVolFlowMaxCool);
    3134              : 
    3135           10 :         } else if (systemType == SystemType::ConstantFlow) {
    3136              : 
    3137           10 :             CompType = "ZoneHVAC:LowTemperatureRadiant:ConstantFlow";
    3138           10 :             CompName = state.dataLowTempRadSys->CFloRadSys(RadSysNum).Name;
    3139              : 
    3140              :             // Why is this not the same thing as the other OpMode enumeration? In the .hh file?
    3141              :             OperatingMode OpMode; // System operating mode
    3142              : 
    3143              :             // Check which operating system it is
    3144           10 :             int HeatNode = state.dataLowTempRadSys->CFloRadSys(RadSysNum).HotWaterInNode;
    3145           10 :             int CoolNode = state.dataLowTempRadSys->CFloRadSys(RadSysNum).ColdWaterInNode;
    3146           10 :             if (HeatNode > 0 && CoolNode > 0) {
    3147            1 :                 OpMode = OperatingMode::ClgHtg;
    3148            9 :             } else if (HeatNode > 0 && CoolNode <= 0) {
    3149            2 :                 OpMode = OperatingMode::HtgOnly;
    3150            7 :             } else if (CoolNode > 0 && HeatNode <= 0) {
    3151            2 :                 OpMode = OperatingMode::ClgOnly;
    3152              :             } else {
    3153            5 :                 OpMode = OperatingMode::OFF; // It shouldn't happen here
    3154              :             }
    3155              : 
    3156           10 :             if (state.dataLowTempRadSys->CFloRadSys(RadSysNum).WaterVolFlowMax == AutoSize) {
    3157            6 :                 IsAutoSize = true;
    3158              :             }
    3159              : 
    3160           10 :             if (state.dataSize->CurZoneEqNum > 0) {
    3161           10 :                 if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) { // simulation continue
    3162            0 :                     if (state.dataLowTempRadSys->CFloRadSys(RadSysNum).WaterVolFlowMax > 0.0) {
    3163            0 :                         BaseSizer::reportSizerOutput(state,
    3164              :                                                      CompType,
    3165            0 :                                                      state.dataLowTempRadSys->CFloRadSys(RadSysNum).Name,
    3166              :                                                      "User-Specified Maximum Water Flow [m3/s]",
    3167            0 :                                                      state.dataLowTempRadSys->CFloRadSys(RadSysNum).WaterVolFlowMax);
    3168              :                     }
    3169              :                 } else { // Autosize or hard-size with sizing run
    3170           10 :                     CheckZoneSizing(state, CompType, state.dataLowTempRadSys->CFloRadSys(RadSysNum).Name);
    3171              :                     // Estimate hot water and chilled water flows
    3172              :                     // Index only if it provides heating to avoid severe error
    3173           10 :                     if (OpMode == OperatingMode::ClgHtg || OpMode == OperatingMode::HtgOnly) {
    3174            3 :                         PltSizHeatNum = MyPlantSizingIndex(state,
    3175              :                                                            CompType,
    3176            3 :                                                            state.dataLowTempRadSys->CFloRadSys(RadSysNum).Name,
    3177            3 :                                                            state.dataLowTempRadSys->CFloRadSys(RadSysNum).HotWaterInNode,
    3178            3 :                                                            state.dataLowTempRadSys->CFloRadSys(RadSysNum).HotWaterOutNode,
    3179              :                                                            ErrorsFound);
    3180              :                     }
    3181           10 :                     if (PltSizHeatNum > 0) {
    3182            3 :                         if (state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).NonAirSysDesHeatLoad >= SmallLoad) {
    3183            3 :                             rho = state.dataPlnt->PlantLoop(state.dataLowTempRadSys->CFloRadSys(RadSysNum).HWPlantLoc.loopNum)
    3184            3 :                                       .glycol->getDensity(state, Constant::HWInitConvTemp, "SizeLowTempRadiantSystem");
    3185            3 :                             Cp = state.dataPlnt->PlantLoop(state.dataLowTempRadSys->CFloRadSys(RadSysNum).HWPlantLoc.loopNum)
    3186            3 :                                      .glycol->getSpecificHeat(state, Constant::HWInitConvTemp, "SizeLowTempRadiantSystem");
    3187            3 :                             WaterVolFlowMaxHeatDes = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).NonAirSysDesHeatLoad /
    3188            3 :                                                      (state.dataSize->PlantSizData(PltSizHeatNum).DeltaT * Cp * rho);
    3189              :                         } else {
    3190            0 :                             WaterVolFlowMaxHeatDes = 0.0;
    3191              :                         }
    3192              :                     } else {
    3193            7 :                         if (OpMode == OperatingMode::ClgHtg || OpMode == OperatingMode::HtgOnly) {
    3194            0 :                             ShowSevereError(state, "Autosizing of water flow requires a heating loop Sizing:Plant object");
    3195            0 :                             ShowContinueError(state,
    3196            0 :                                               format("Occurs in ZoneHVAC:LowTemperatureRadiant:ConstantFlow Object={}",
    3197            0 :                                                      state.dataLowTempRadSys->CFloRadSys(RadSysNum).Name));
    3198            0 :                             ErrorsFound = true;
    3199              :                         }
    3200              :                     }
    3201              : 
    3202              :                     // Index only if it provides cooling system to avoid severe error
    3203           10 :                     if (OpMode == OperatingMode::ClgHtg || OpMode == OperatingMode::ClgOnly) {
    3204            3 :                         PltSizCoolNum = MyPlantSizingIndex(state,
    3205              :                                                            CompType,
    3206            3 :                                                            state.dataLowTempRadSys->CFloRadSys(RadSysNum).Name,
    3207            3 :                                                            state.dataLowTempRadSys->CFloRadSys(RadSysNum).ColdWaterInNode,
    3208            3 :                                                            state.dataLowTempRadSys->CFloRadSys(RadSysNum).ColdWaterOutNode,
    3209              :                                                            ErrorsFound);
    3210              :                     }
    3211           10 :                     if (PltSizCoolNum > 0) {
    3212            3 :                         if (state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).NonAirSysDesCoolLoad >= SmallLoad) {
    3213            3 :                             rho = state.dataPlnt->PlantLoop(state.dataLowTempRadSys->CFloRadSys(RadSysNum).CWPlantLoc.loopNum)
    3214            3 :                                       .glycol->getDensity(state, Constant::CWInitConvTemp, "SizeLowTempRadiantSystem");
    3215            3 :                             Cp = state.dataPlnt->PlantLoop(state.dataLowTempRadSys->CFloRadSys(RadSysNum).CWPlantLoc.loopNum)
    3216            3 :                                      .glycol->getSpecificHeat(state, Constant::CWInitConvTemp, "SizeLowTempRadiantSystem");
    3217            3 :                             WaterVolFlowMaxCoolDes = state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).NonAirSysDesCoolLoad /
    3218            3 :                                                      (state.dataSize->PlantSizData(PltSizCoolNum).DeltaT * Cp * rho);
    3219              :                         } else {
    3220            0 :                             WaterVolFlowMaxCoolDes = 0.0;
    3221              :                         }
    3222              :                     } else {
    3223            7 :                         if (OpMode == OperatingMode::ClgHtg || OpMode == OperatingMode::ClgOnly) {
    3224            0 :                             ShowSevereError(state, "Autosizing of water flow requires a cooling loop Sizing:Plant object");
    3225            0 :                             ShowContinueError(state,
    3226            0 :                                               format("Occurs in ZoneHVAC:LowTemperatureRadiant:ConstantFlow Object={}",
    3227            0 :                                                      state.dataLowTempRadSys->CFloRadSys(RadSysNum).Name));
    3228            0 :                             ErrorsFound = true;
    3229              :                         }
    3230              :                     }
    3231              : 
    3232              :                     // Determine maximum water flow rate depending upon system type
    3233           10 :                     if (OpMode == OperatingMode::ClgHtg) {
    3234            1 :                         WaterVolFlowMaxDes = std::max(WaterVolFlowMaxHeatDes, WaterVolFlowMaxCoolDes);
    3235            9 :                     } else if (OpMode == OperatingMode::ClgOnly) {
    3236            2 :                         WaterVolFlowMaxDes = WaterVolFlowMaxCoolDes;
    3237            7 :                     } else if (OpMode == OperatingMode::HtgOnly) {
    3238            2 :                         WaterVolFlowMaxDes = WaterVolFlowMaxHeatDes;
    3239              :                     } else {
    3240            5 :                         WaterVolFlowMaxDes = 0.0;
    3241              :                     }
    3242              : 
    3243           10 :                     if (IsAutoSize) {
    3244            6 :                         state.dataLowTempRadSys->CFloRadSys(RadSysNum).WaterVolFlowMax = WaterVolFlowMaxDes;
    3245           12 :                         BaseSizer::reportSizerOutput(state,
    3246              :                                                      CompType,
    3247            6 :                                                      state.dataLowTempRadSys->CFloRadSys(RadSysNum).Name,
    3248              :                                                      "Design Size Maximum Water Flow [m3/s]",
    3249              :                                                      WaterVolFlowMaxDes);
    3250              :                     } else { // hard-size with sizing data
    3251            4 :                         if (state.dataLowTempRadSys->CFloRadSys(RadSysNum).WaterVolFlowMax > 0.0 && WaterVolFlowMaxDes > 0.0) {
    3252            0 :                             WaterVolFlowMaxUser = state.dataLowTempRadSys->CFloRadSys(RadSysNum).WaterVolFlowMax;
    3253            0 :                             BaseSizer::reportSizerOutput(state,
    3254              :                                                          CompType,
    3255            0 :                                                          state.dataLowTempRadSys->CFloRadSys(RadSysNum).Name,
    3256              :                                                          "Design Size Maximum Water Flow [m3/s]",
    3257              :                                                          WaterVolFlowMaxDes,
    3258              :                                                          "User-Specified Maximum Water Flow [m3/s]",
    3259              :                                                          WaterVolFlowMaxUser);
    3260            0 :                             if (state.dataGlobal->DisplayExtraWarnings) {
    3261            0 :                                 if ((std::abs(WaterVolFlowMaxDes - WaterVolFlowMaxUser) / WaterVolFlowMaxUser) >
    3262            0 :                                     state.dataSize->AutoVsHardSizingThreshold) {
    3263            0 :                                     ShowMessage(state,
    3264            0 :                                                 format("SizeLowTempRadiantSystem: Potential issue with equipment sizing for "
    3265              :                                                        "ZoneHVAC:LowTemperatureRadiant:ConstantFlow = \" {}\".",
    3266            0 :                                                        state.dataLowTempRadSys->CFloRadSys(RadSysNum).Name));
    3267            0 :                                     ShowContinueError(state, format("User-Specified Maximum Water Flow of {:.5R} [m3/s]", WaterVolFlowMaxUser));
    3268            0 :                                     ShowContinueError(state,
    3269            0 :                                                       format("differs from Design Size Maximum Water Flow of {:.5R} [m3/s]", WaterVolFlowMaxDes));
    3270            0 :                                     ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
    3271            0 :                                     ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
    3272              :                                 }
    3273              :                             }
    3274              :                         }
    3275              :                     }
    3276              :                 }
    3277              :             }
    3278              : 
    3279           10 :             IsAutoSize = false;
    3280           10 :             if (state.dataLowTempRadSys->CFloRadSys(RadSysNum).TubeLength == AutoSize) {
    3281            1 :                 IsAutoSize = true;
    3282              :             }
    3283              : 
    3284           10 :             if (state.dataSize->CurZoneEqNum > 0) {
    3285           10 :                 if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) { // simulation continue
    3286            0 :                     if (state.dataLowTempRadSys->CFloRadSys(RadSysNum).TubeLength > 0.0) {
    3287            0 :                         BaseSizer::reportSizerOutput(state,
    3288              :                                                      "ZoneHVAC:LowTemperatureRadiant:ConstantFlow",
    3289            0 :                                                      state.dataLowTempRadSys->CFloRadSys(RadSysNum).Name,
    3290              :                                                      "User-Specified Hydronic Tubing Length [m]",
    3291            0 :                                                      state.dataLowTempRadSys->CFloRadSys(RadSysNum).TubeLength);
    3292              :                     }
    3293              :                 } else { // Autosize or hard-size with sizing run
    3294              :                     // CheckZoneSizing is not required here because the tube length calculation is not dependent on zone sizing calculation results
    3295           10 :                     TubeLengthDes = state.dataLowTempRadSys->CFloRadSys(RadSysNum).sizeRadiantSystemTubeLength(state);
    3296           10 :                     if (IsAutoSize) {
    3297            1 :                         state.dataLowTempRadSys->CFloRadSys(RadSysNum).TubeLength = TubeLengthDes;
    3298            2 :                         BaseSizer::reportSizerOutput(state,
    3299              :                                                      "ZoneHVAC:LowTemperatureRadiant:ConstantFlow",
    3300            1 :                                                      state.dataLowTempRadSys->CFloRadSys(RadSysNum).Name,
    3301              :                                                      "Design Size Hydronic Tubing Length [m]",
    3302              :                                                      TubeLengthDes);
    3303              :                     } else { // hard-size with sizing data
    3304            9 :                         if (state.dataLowTempRadSys->CFloRadSys(RadSysNum).TubeLength > 0.0 && TubeLengthDes > 0.0) {
    3305            0 :                             TubeLengthUser = state.dataLowTempRadSys->CFloRadSys(RadSysNum).TubeLength;
    3306            0 :                             BaseSizer::reportSizerOutput(state,
    3307              :                                                          "ZoneHVAC:LowTemperatureRadiant:ConstantFlow",
    3308            0 :                                                          state.dataLowTempRadSys->CFloRadSys(RadSysNum).Name,
    3309              :                                                          "Design Size Hydronic Tubing Length [m]",
    3310              :                                                          TubeLengthDes,
    3311              :                                                          "User-Specified Hydronic Tubing Length [m]",
    3312              :                                                          TubeLengthUser);
    3313            0 :                             if (state.dataGlobal->DisplayExtraWarnings) {
    3314            0 :                                 if ((std::abs(TubeLengthDes - TubeLengthUser) / TubeLengthUser) > state.dataSize->AutoVsHardSizingThreshold) {
    3315            0 :                                     ShowMessage(state,
    3316            0 :                                                 format("SizeLowTempRadiantSystem: Potential issue with equipment sizing for "
    3317              :                                                        "ZoneHVAC:LowTemperatureRadiant:ConstantFlow = \" {}\".",
    3318            0 :                                                        state.dataLowTempRadSys->CFloRadSys(RadSysNum).Name));
    3319            0 :                                     ShowContinueError(state, format("User-Specified Hydronic Tubing Length of {:.5R} [m]", TubeLengthUser));
    3320            0 :                                     ShowContinueError(state, format("differs from Design Size Hydronic Tubing Length of {:.5R} [m]", TubeLengthDes));
    3321            0 :                                     ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
    3322            0 :                                     ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
    3323              :                                 }
    3324              :                             }
    3325              :                         }
    3326              :                     }
    3327              :                 }
    3328              :             }
    3329              : 
    3330           11 :             for (SurfNum = 1; SurfNum <= state.dataLowTempRadSys->CFloRadSys(RadSysNum).NumOfSurfaces; ++SurfNum) {
    3331            1 :                 if (state.dataLowTempRadSys->CFloRadSys(RadSysNum).NumCircCalcMethod == CircuitCalc::CalculateFromLength) {
    3332            0 :                     state.dataLowTempRadSys->CFloRadSys(RadSysNum).NumCircuits(SurfNum) =
    3333            0 :                         (state.dataLowTempRadSys->CFloRadSys(RadSysNum).SurfaceFrac(SurfNum) *
    3334            0 :                          state.dataLowTempRadSys->CFloRadSys(RadSysNum).TubeLength) /
    3335            0 :                         state.dataLowTempRadSys->CFloRadSys(RadSysNum).CircLength;
    3336            0 :                     state.dataLowTempRadSys->CFloRadSys(RadSysNum).NumCircuits(SurfNum) =
    3337            0 :                         max(state.dataLowTempRadSys->CFloRadSys(RadSysNum).NumCircuits(SurfNum), 1.0);
    3338              :                 } else {
    3339            1 :                     state.dataLowTempRadSys->CFloRadSys(RadSysNum).NumCircuits(SurfNum) = 1.0;
    3340              :                 }
    3341              :             }
    3342           10 :             if (state.dataLowTempRadSys->CFloRadSys(RadSysNum).HotWaterInNode > 0) {
    3343            6 :                 RegisterPlantCompDesignFlow(state,
    3344            3 :                                             state.dataLowTempRadSys->CFloRadSys(RadSysNum).HotWaterInNode,
    3345            3 :                                             state.dataLowTempRadSys->CFloRadSys(RadSysNum).WaterVolFlowMax);
    3346              :             }
    3347           10 :             if (state.dataLowTempRadSys->CFloRadSys(RadSysNum).ColdWaterInNode > 0) {
    3348            6 :                 RegisterPlantCompDesignFlow(state,
    3349            3 :                                             state.dataLowTempRadSys->CFloRadSys(RadSysNum).ColdWaterInNode,
    3350            3 :                                             state.dataLowTempRadSys->CFloRadSys(RadSysNum).WaterVolFlowMax);
    3351              :             }
    3352              :         }
    3353              : 
    3354           20 :         if (ErrorsFound) {
    3355            0 :             ShowFatalError(state, "Preceding sizing errors cause program termination");
    3356              :         }
    3357           20 :     }
    3358              : 
    3359           25 :     Real64 HydronicSystemBaseData::sizeRadiantSystemTubeLength(EnergyPlusData &state)
    3360              :     {
    3361              : 
    3362              :         // SUBROUTINE INFORMATION:
    3363              :         //       AUTHOR         Rick Strand
    3364              :         //       DATE WRITTEN   August 2017
    3365              : 
    3366              :         // PURPOSE OF THIS SUBROUTINE:
    3367              :         // This subroutine figures out the tube length based on the spacing of tubes.
    3368              :         // For single surface systems, this is fairly easy as there is only one spacing
    3369              :         // to deal with.  For multi-surface systems, more work is necessary because each
    3370              :         // surface could use a different spacing.
    3371              : 
    3372              :         // Return value
    3373              :         Real64 sizeRadiantSystemTubeLength;
    3374              : 
    3375           25 :         Real64 tubeLength(0.0); // temporary holding place for the function calculation
    3376              : 
    3377           40 :         for (int surfNum = 1; surfNum <= this->NumOfSurfaces; ++surfNum) {
    3378           15 :             auto &thisHydrSysSurf = state.dataSurface->Surface(this->SurfacePtr(surfNum));
    3379           15 :             auto const &thisHydrSpacing = state.dataConstruction->Construct(thisHydrSysSurf.Construction).ThicknessPerpend;
    3380           15 :             if ((thisHydrSpacing > 0.005) && (thisHydrSpacing < 0.5)) { // limit allowable spacing to between 1cm and 1m
    3381           11 :                 tubeLength += thisHydrSysSurf.Area / (2.0 * thisHydrSpacing);
    3382              :             } else { // if not in allowable limit, default back to 0.15m (15cm or 6 inches)
    3383            4 :                 tubeLength += thisHydrSysSurf.Area / 0.15;
    3384              :             }
    3385              :         }
    3386              : 
    3387           25 :         sizeRadiantSystemTubeLength = tubeLength;
    3388           25 :         return sizeRadiantSystemTubeLength;
    3389              :     }
    3390              : 
    3391            2 :     void VariableFlowRadiantSystemData::calculateLowTemperatureRadiantSystem(EnergyPlusData &state,
    3392              :                                                                              Real64 &LoadMet) // load met by the radiant system, in Watts
    3393              :     {
    3394              : 
    3395              :         // SUBROUTINE INFORMATION:
    3396              :         //       AUTHOR         Rick Strand
    3397              :         //       DATE WRITTEN   November 2000
    3398              : 
    3399              :         // PURPOSE OF THIS SUBROUTINE:
    3400              :         // This subroutine does all of the stuff that is necessary to simulate
    3401              :         // a low temperature hydronic radiant heating/cooling system.  Calls are
    3402              :         // made to appropriate subroutines either in this module or outside of it.
    3403              : 
    3404              :         // METHODOLOGY EMPLOYED:
    3405              :         // Follows the methods used by many other pieces of zone equipment.
    3406              :         // Much like a water coil, a hydronic system will use the ControlCompOutput
    3407              :         // routine to determine what fraction of capacity the unit should be
    3408              :         // functioning at by controlling the flow rate of water to the element.
    3409              : 
    3410              :         // REFERENCES:
    3411              :         // Other EnergyPlus modules
    3412              :         // IBLAST-QTF research program, completed in January 1995 (unreleased)
    3413              :         // Strand, R.K. 1995. "Heat Source Transfer Functions and Their Application to
    3414              :         //   Low Temperature Radiant Heating Systems", Ph.D. dissertation, University
    3415              :         //   of Illinois at Urbana-Champaign, Department of Mechanical and Industrial
    3416              :         //   Engineering.
    3417              :         // Seem, J.E. 1986. "Heat Transfer in Buildings", Ph.D. dissertation, University
    3418              :         //   of Wisconsin-Madison.
    3419              : 
    3420              :         // Using/Aliasing
    3421              :         using DataHeatBalance::ZoneData;
    3422              :         using HVAC::SmallLoad;
    3423              :         using PlantUtilities::SetComponentFlowRate;
    3424              : 
    3425              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    3426              :         Real64 ActWaterFlow; // actual water flow for heating or cooling [kg/sec]
    3427              :         Real64 ControlTemp;  // temperature of whatever is controlling the radiant system
    3428              :         Real64 MassFlowFrac; // fraction of the maximum water flow rate as determined by the control algorithm
    3429              :         Real64 MaxWaterFlow; // maximum water flow for heating or cooling [kg/sec]
    3430              :         Real64 OffTempCool;  // temperature at which the flow rate throttles back to zero for cooling
    3431              :         Real64 OffTempHeat;  // temperature at which the flow rate throttles back to zero for heating
    3432              :         Real64 mdot;         // local temporary for fluid mass flow rate
    3433              :         bool SysRunning;     // True when system is running
    3434              : 
    3435              :         VarFlowRadDesignData variableFlowDesignDataObject =                           // Is this intended to be a copy?
    3436            2 :             state.dataLowTempRadSys->HydronicRadiantSysDesign(this->DesignObjectPtr); // Contains the data for variable flow hydronic systems
    3437              : 
    3438            2 :         MaxWaterFlow = 0.0;
    3439            2 :         ActWaterFlow = 0.0;
    3440            2 :         this->opMode = OpMode::None;
    3441            2 :         SysRunning = true;
    3442              : 
    3443            2 :         if (this->availSched->getCurrentVal() <= 0) {
    3444              : 
    3445              :             // Unit is off or has no load upon it; set the flow rates to zero and then
    3446              :             // simulate the components with the no flow conditions
    3447            0 :             for (int SurfNum = 1; SurfNum <= this->NumOfSurfaces; ++SurfNum) {
    3448            0 :                 int SurfNum2 = this->SurfacePtr(SurfNum);
    3449            0 :                 auto &surface = state.dataSurface->Surface(SurfNum2);
    3450            0 :                 state.dataHeatBalFanSys->QRadSysSource(SurfNum2) = 0.0;
    3451            0 :                 if (surface.ExtBoundCond > 0 && surface.ExtBoundCond != SurfNum2)
    3452            0 :                     state.dataHeatBalFanSys->QRadSysSource(surface.ExtBoundCond) = 0.0; // Also zero the other side of an interzone
    3453              :             }
    3454            0 :             if (this->HeatingSystem) {
    3455            0 :                 mdot = 0.0;
    3456            0 :                 SetComponentFlowRate(state, mdot, this->HotWaterInNode, this->HotWaterOutNode, this->HWPlantLoc);
    3457              :             }
    3458            0 :             if (this->CoolingSystem) {
    3459            0 :                 mdot = 0.0;
    3460            0 :                 SetComponentFlowRate(state, mdot, this->ColdWaterInNode, this->ColdWaterOutNode, this->CWPlantLoc);
    3461              :             }
    3462              :         } else { // Unit might be on-->this section is intended to control the water mass flow rate being
    3463              :             // sent to the radiant system
    3464              : 
    3465            2 :             ControlTemp = this->setRadiantSystemControlTemperature(state, variableFlowDesignDataObject.VarFlowControlType);
    3466              : 
    3467            2 :             if (variableFlowDesignDataObject.heatSetptSched != nullptr) {
    3468              :                 //                OffTempHeat = this->setOffTemperatureLowTemperatureRadiantSystem(state, this->HotSetptSchedPtr,
    3469              :                 //                this->HotThrottlRange);
    3470              :                 Real64 a;
    3471            2 :                 a = variableFlowDesignDataObject.HotThrottlRange; // Why are we doing this?
    3472            2 :                 OffTempHeat = this->setOffTemperatureLowTemperatureRadiantSystem(state,
    3473            2 :                                                                                  variableFlowDesignDataObject.heatSetptSched,
    3474              :                                                                                  variableFlowDesignDataObject.HotThrottlRange,
    3475              :                                                                                  variableFlowDesignDataObject.VarFlowSetpointType);
    3476              :             } else { // This system is not capable of heating, set OffTempHeat to something really low
    3477            0 :                 OffTempHeat = state.dataLowTempRadSys->LowTempHeating;
    3478              :             }
    3479            2 :             if (variableFlowDesignDataObject.coolSetptSched != nullptr) {
    3480            2 :                 OffTempCool = this->setOffTemperatureLowTemperatureRadiantSystem(state,
    3481            2 :                                                                                  variableFlowDesignDataObject.coolSetptSched,
    3482            2 :                                                                                  -variableFlowDesignDataObject.ColdThrottlRange,
    3483              :                                                                                  variableFlowDesignDataObject.VarFlowSetpointType);
    3484              :             } else { // This system is not capable of cooling, set OffTempCool to something really high
    3485            0 :                 OffTempCool = state.dataLowTempRadSys->HighTempCooling;
    3486              :             }
    3487              : 
    3488              :             // Check for an illogical condition where a user enters controls that could
    3489              :             // potentially be heating or cooling at a particular control temperature
    3490            2 :             if (OffTempHeat > OffTempCool) {
    3491            0 :                 MassFlowFrac = 0.0;
    3492            0 :                 ShowSevereError(state, format("Overlapping heating and cooling control temps in radiant system: {}", this->Name));
    3493            0 :                 ShowFatalError(state, "Preceding condition causes termination.");
    3494              : 
    3495              :             } else { // Temperatures for heating and cooling do not overlap--calculate the mass flow fraction
    3496              : 
    3497            2 :                 if (ControlTemp < OffTempHeat && this->HeatingSystem) { // Heating mode
    3498            0 :                     this->opMode = OpMode::Heat;
    3499            2 :                 } else if (ControlTemp > OffTempCool && this->CoolingSystem) { // Cooling mode
    3500            0 :                     this->opMode = OpMode::Cool;
    3501              :                 }
    3502              : 
    3503            2 :                 this->setOperatingModeBasedOnChangeoverDelay(state);
    3504              : 
    3505            2 :                 if (this->opMode == OpMode::Heat) {
    3506            0 :                     MaxWaterFlow = this->WaterFlowMaxHeat;
    3507            0 :                     MassFlowFrac = this->calculateOperationalFraction(OffTempHeat, ControlTemp, variableFlowDesignDataObject.HotThrottlRange);
    3508            2 :                 } else if (this->opMode == OpMode::Cool) {
    3509            0 :                     MaxWaterFlow = this->WaterFlowMaxCool;
    3510            0 :                     MassFlowFrac = this->calculateOperationalFraction(OffTempCool, ControlTemp, variableFlowDesignDataObject.ColdThrottlRange);
    3511              :                 } else {
    3512            2 :                     MassFlowFrac = 0.0;
    3513              :                 }
    3514              :             }
    3515              : 
    3516              :             // Calculate and limit the water flow rate
    3517            2 :             ActWaterFlow = MassFlowFrac * MaxWaterFlow;
    3518            2 :             if (ActWaterFlow < DataBranchAirLoopPlant::MassFlowTolerance) ActWaterFlow = 0.0;
    3519            2 :             if (this->EMSOverrideOnWaterMdot) ActWaterFlow = this->EMSWaterMdotOverrideValue;
    3520              : 
    3521            2 :             if (this->opMode == OpMode::Heat) {
    3522            0 :                 if (this->HeatingSystem) {
    3523            0 :                     SetComponentFlowRate(state, ActWaterFlow, this->HotWaterInNode, this->HotWaterOutNode, this->HWPlantLoc);
    3524              :                 } else { // not heating system
    3525            0 :                     SysRunning = false;
    3526              :                 }
    3527            2 :             } else if (this->opMode == OpMode::Cool) {
    3528            0 :                 if (this->CoolingSystem) {
    3529            0 :                     SetComponentFlowRate(state, ActWaterFlow, this->ColdWaterInNode, this->ColdWaterOutNode, this->CWPlantLoc);
    3530              :                 } else { // not cooling system
    3531            0 :                     SysRunning = false;
    3532              :                 }
    3533              :             }
    3534              : 
    3535              :             // Now simulate the system...
    3536            2 :             if (((this->opMode == OpMode::Heat) || (this->opMode == OpMode::Cool)) && SysRunning)
    3537            0 :                 this->calculateLowTemperatureRadiantSystemComponents(state, LoadMet, SystemType::Hydronic);
    3538              :         }
    3539            2 :     }
    3540              : 
    3541            0 :     void VariableFlowRadiantSystemData::calculateLowTemperatureRadiantSystemComponents(
    3542              :         EnergyPlusData &state,
    3543              :         Real64 &LoadMet,
    3544              :         SystemType const typeOfRadiantSystem) // Load met by the low temperature radiant system, in Watts
    3545              :     {
    3546              : 
    3547              :         // SUBROUTINE INFORMATION:
    3548              :         //       AUTHOR         Rick Strand
    3549              :         //       DATE WRITTEN   November 2000
    3550              :         //       MODIFIED       Sep 2011 LKL/BG - resimulate only zones needing it for Radiant systems
    3551              : 
    3552              :         // PURPOSE OF THIS SUBROUTINE:
    3553              :         // This subroutine solves the radiant system based on how much water is (and
    3554              :         // the conditions of the water) supplied to the radiant system.
    3555              : 
    3556              :         // METHODOLOGY EMPLOYED:
    3557              :         // Use heat exchanger formulas to obtain the heat source/sink for the radiant
    3558              :         // system based on the inlet conditions and flow rate of water.  Once that is
    3559              :         // determined, recalculate the surface heat balances to reflect this heat
    3560              :         // addition/subtraction.  The load met by the system is determined by the
    3561              :         // difference between the convection from all surfaces in the zone when
    3562              :         // there was no radiant system output and with a source/sink added.
    3563              : 
    3564              :         // REFERENCES:
    3565              :         // IBLAST-QTF research program, completed in January 1995 (unreleased)
    3566              :         // Strand, R.K. 1995. "Heat Source Transfer Functions and Their Application to
    3567              :         //   Low Temperature Radiant Heating Systems", Ph.D. dissertation, University
    3568              :         //   of Illinois at Urbana-Champaign, Department of Mechanical and Industrial
    3569              :         //   Engineering.
    3570              : 
    3571            0 :         auto &Zone = state.dataHeatBal->Zone;
    3572              : 
    3573              :         // Using/Aliasing
    3574              :         using PlantUtilities::SetComponentFlowRate;
    3575              : 
    3576              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    3577              :         Real64 DewPointTemp;      // Dew-point temperature based on the zone air conditions
    3578              :         Real64 EpsMdotCp;         // Epsilon (heat exchanger terminology) times water mass flow rate times water specific heat
    3579              :         Real64 FullWaterMassFlow; // Original water mass flow rate before reducing the flow for condensation concerns
    3580              :         Real64 LowestRadSurfTemp; // Lowest surface temperature of a radiant system (when condensation is a concern)
    3581              :         Real64 PredictedCondTemp; // Temperature at which condensation is predicted (includes user parameter)
    3582              :         Real64 ReductionFrac;     // Fraction that the flow should be reduced to avoid condensation
    3583              :         Real64 SysWaterMassFlow;  // System level water mass flow rate (includes effect of zone multiplier)
    3584              :         Real64 WaterMassFlow;     // Water mass flow rate in the radiant system, kg/s
    3585              :         int WaterNodeIn;          // Node number of the water entering the radiant system
    3586              :         Real64 WaterTempIn;       // Temperature of the water entering the radiant system, in C
    3587              :         Real64 ZeroFlowSurfTemp;  // Temperature of radiant surface when flow is zero
    3588              :         int ZoneNum;              // Zone pointer for this radiant system
    3589              : 
    3590              :         VarFlowRadDesignData variableFlowDesignDataObject =                           // Is this intended to be a deep copy?
    3591            0 :             state.dataLowTempRadSys->HydronicRadiantSysDesign(this->DesignObjectPtr); // Contains the data for variable flow hydronic systems
    3592              : 
    3593            0 :         auto &Surface = state.dataSurface->Surface;
    3594              : 
    3595              :         Real64 Ca; // Coefficients to relate the inlet water temperature to the heat source
    3596              :         Real64 Cb;
    3597              :         Real64 Cc;
    3598              :         Real64 Cd;
    3599              :         Real64 Ce;
    3600              :         Real64 Cf;
    3601              :         Real64 Cg;
    3602              :         Real64 Ch;
    3603              :         Real64 Ci;
    3604              :         Real64 Cj;
    3605              :         Real64 Ck;
    3606              :         Real64 Cl;
    3607              :         // For more info on Ca through Cl, see comments below
    3608              : 
    3609              :         // First, apply heat exchanger logic to find the heat source/sink to the system.
    3610              :         // This involves finding out the heat transfer characteristics of the hydronic
    3611              :         // loop and then applying the equations derived on pp. 113-118 of the dissertation.
    3612              : 
    3613              :         // Set the conditions on the water side inlet
    3614            0 :         switch (this->opMode) {
    3615            0 :         case OpMode::Heat: {
    3616            0 :             WaterNodeIn = this->HotWaterInNode;
    3617            0 :         } break;
    3618            0 :         case OpMode::Cool: {
    3619            0 :             WaterNodeIn = this->ColdWaterInNode;
    3620            0 :         } break;
    3621            0 :         default: {
    3622            0 :             WaterNodeIn = 0; // Suppress uninitialized warning
    3623            0 :             ShowSevereError(state, "Illegal low temperature radiant system operating mode");
    3624            0 :             ShowContinueError(state, format("Occurs in Radiant System={}", this->Name));
    3625            0 :             ShowFatalError(state, "Preceding condition causes termination.");
    3626            0 :         } break;
    3627              :         }
    3628            0 :         ZoneNum = this->ZonePtr;
    3629            0 :         SysWaterMassFlow = state.dataLoopNodes->Node(WaterNodeIn).MassFlowRate;
    3630            0 :         WaterMassFlow = state.dataLoopNodes->Node(WaterNodeIn).MassFlowRate / double(Zone(ZoneNum).Multiplier * Zone(ZoneNum).ListMultiplier);
    3631            0 :         WaterTempIn = state.dataLoopNodes->Node(WaterNodeIn).Temp;
    3632              : 
    3633            0 :         if (WaterMassFlow <= 0.0) {
    3634              :             // No flow or below minimum allowed so there is no heat source/sink
    3635              :             // This is possible with a mismatch between system and plant operation
    3636              :             // or a slight mismatch between zone and system controls.  This is not
    3637              :             // necessarily a "problem" so this exception is necessary in the code.
    3638            0 :             for (int RadSurfNum = 1; RadSurfNum <= this->NumOfSurfaces; ++RadSurfNum) {
    3639            0 :                 int SurfNum = this->SurfacePtr(RadSurfNum);
    3640            0 :                 state.dataHeatBalFanSys->QRadSysSource(SurfNum) = 0.0;
    3641            0 :                 if (Surface(SurfNum).ExtBoundCond > 0 && Surface(SurfNum).ExtBoundCond != SurfNum)
    3642            0 :                     state.dataHeatBalFanSys->QRadSysSource(Surface(SurfNum).ExtBoundCond) = 0.0; // Also zero the other side of an interzone
    3643              :             }
    3644              : 
    3645              :         } else {
    3646              : 
    3647            0 :             for (int RadSurfNum = 1; RadSurfNum <= this->NumOfSurfaces; ++RadSurfNum) {
    3648              : 
    3649            0 :                 int SurfNum = this->SurfacePtr(RadSurfNum);
    3650              :                 // Determine the heat exchanger "effectiveness" term
    3651              : 
    3652            0 :                 EpsMdotCp = calculateHXEffectivenessTerm(state,
    3653              :                                                          SurfNum,
    3654              :                                                          WaterTempIn,
    3655              :                                                          WaterMassFlow,
    3656            0 :                                                          this->SurfaceFrac(RadSurfNum),
    3657            0 :                                                          this->NumCircuits(RadSurfNum),
    3658              :                                                          this->DesignObjectPtr,
    3659              :                                                          typeOfRadiantSystem);
    3660              : 
    3661              :                 // Obtain the heat balance coefficients and calculate the intermediate coefficients
    3662              :                 // linking the inlet water temperature to the heat source/sink to the radiant system.
    3663              :                 // The coefficients are based on the following development...
    3664              :                 // The heat balance equations at the outside and inside surfaces are of the form:
    3665              :                 //   Tinside  = Ca + Cb*Toutside + Cc*q"
    3666              :                 //   Toutside = Cd + Ce*Tinside  + Cf*q"
    3667              :                 //   Tsource  = Cg + Ch*q"       + Ci*Tinside + Cj*Toutside
    3668              :                 // where:
    3669              :                 //   Tinside is the temperature at the inside surface
    3670              :                 //   Toutside is the temperature at the outside surface
    3671              :                 //   Tsource is the temperature within the radiant system at the location of the source/sink
    3672              :                 //   Ca is all of the other terms in the inside heat balance (solar, LW exchange, conduction history terms, etc.)
    3673              :                 //   Cb is the current cross CTF term
    3674              :                 //   Cc is the QTF inside term for the current heat source/sink
    3675              :                 //   Cd is all of the other terms in the outside heat balance (solar, LW exchange, conduction history terms, etc.)
    3676              :                 //   Ce is the current cross CTF term (should be equal to Cb)
    3677              :                 //   Cf is the QTF outside term for the current heat source/sink
    3678              :                 //   Cg is the summation of all temperature and source history terms at the source/sink location
    3679              :                 //   Ch is the QTF term at the source/sink location for the current heat source/sink
    3680              :                 //   Ci is the CTF inside term for the current inside surface temperature
    3681              :                 //   Cj is the CTF outside term for the current outside surface temperature
    3682              :                 // Note that it is necessary to not use "slow conduction" assumptions because the
    3683              :                 // source/sink has an impact on BOTH the inside and outside surface heat balances.
    3684              :                 // Hence the more general formulation.
    3685              :                 // The first two T equations above can be solved to remove the other surface temperature.
    3686              :                 // This results in the following equations:
    3687              :                 //   Tinside  = Ca + Cb*(Cd + Ce*Tinside + Cf*q") + Cc*q"   or...
    3688              :                 //   Tinside  = (Ca + Cb*Cd + (Cc+Cb*Cf)*q") / (1 - Ce*Cb)
    3689              :                 //   Toutside = Cd + Ce*(Ca + Cb*Toutside + Cc*q") + Cf*q"  or...
    3690              :                 //   Toutside = (Cd + Ce*Ca + (Cf+Ce*Cc)*q") / (1 - Ce*Cb)
    3691              :                 // Substituting the new equations for Tinside and Toutside as a function of C and q"
    3692              :                 // into the equation for Tsource...
    3693              :                 //   Tsource  = Cg + Ch*q" + Ci*((Ca + Cb*Cd + (Cc+Cb*Cf)*q") / (1 - Ce*Cb)) &
    3694              :                 //                         + Cj*((Cd + Ce*Ca + (Cf+Ce*Cc)*q") / (1 - Ce*Cb))
    3695              :                 // Or rearranging this to get Tsource as a function of q", we get...
    3696              :                 //   Tsource  =  Cg + ((Ci*(Ca + Cb*Cd) + Cj*(Cd + Ce*Ca))/(1-Ce*Cb)) &
    3697              :                 //             +(Ch + ((Ci*(Cc + Cb*Cf) + Cj*(Cf + Ce*Cc))/(1-Ce*Cb)))*q"
    3698              :                 // Or in a slightly simpler form...
    3699              :                 //   Tsource  = Ck + Cl*q"
    3700              :                 // where:
    3701              :                 //   Ck = Cg + ((Ci*(Ca + Cb*Cd) + Cj*(Cd + Ce*Ca))/(1-Ce*Cb))
    3702              :                 //   Cl = Ch + ((Ci*(Cc + Cb*Cf) + Cj*(Cf + Ce*Cc))/(1-Ce*Cb))
    3703              :                 // Note also that from heat exchanger "algebra", we have:
    3704              :                 //   q = epsilon*qmax    and    qmax = Mdot*Cp*(Twaterin-Tsource)
    3705              :                 // So...
    3706              :                 //   q" = q/Area = (epsilon*Mdot*Cp/Area)*(Twaterin-Tsource)
    3707              :                 // Or rearranging this equation:
    3708              :                 //   Tsource = -(q"*A/(epsilon*Mdot*Cp)) + Twaterin
    3709              :                 // Setting this equation equal to the other equation for Tsource a couple lines up
    3710              :                 // and rearranging to solve for q"...
    3711              :                 //   q" = (Twaterin - Ck) / (Cl + (A/(epsilon*Mdot*Cp))
    3712              :                 // or
    3713              :                 //   q  = (Twaterin - Ck) / ((Cl/A) + (1/epsilon*Mdot*Cp))
    3714              :                 // or
    3715              :                 //   q  = epsilon*Mdot*Cp*(Twaterin - Ck) / (1+(epsilon*Mdot*Cp*Cl/A))
    3716              :                 // which is the desired result, that is the heat source or sink to the radiant
    3717              :                 // system as a function of the water inlet temperature (flow rate is also in there
    3718              :                 // as well as all of the heat balance terms "hidden" in Ck and Cl).
    3719            0 :                 int ConstrNum = Surface(SurfNum).Construction;
    3720            0 :                 auto const &thisConstruct = state.dataConstruction->Construct(ConstrNum);
    3721              : 
    3722            0 :                 if (Surface(SurfNum).HeatTransferAlgorithm == DataSurfaces::HeatTransferModel::CTF) {
    3723              : 
    3724            0 :                     Ca = state.dataHeatBalFanSys->RadSysTiHBConstCoef(SurfNum);
    3725            0 :                     Cb = state.dataHeatBalFanSys->RadSysTiHBToutCoef(SurfNum);
    3726            0 :                     Cc = state.dataHeatBalFanSys->RadSysTiHBQsrcCoef(SurfNum);
    3727              : 
    3728            0 :                     Cd = state.dataHeatBalFanSys->RadSysToHBConstCoef(SurfNum);
    3729            0 :                     Ce = state.dataHeatBalFanSys->RadSysToHBTinCoef(SurfNum);
    3730            0 :                     Cf = state.dataHeatBalFanSys->RadSysToHBQsrcCoef(SurfNum);
    3731              : 
    3732            0 :                     Cg = state.dataHeatBalFanSys->CTFTsrcConstPart(SurfNum);
    3733            0 :                     Ch = thisConstruct.CTFTSourceQ[0];
    3734            0 :                     Ci = thisConstruct.CTFTSourceIn[0];
    3735            0 :                     Cj = thisConstruct.CTFTSourceOut[0];
    3736              : 
    3737            0 :                     Ck = Cg + ((Ci * (Ca + Cb * Cd) + Cj * (Cd + Ce * Ca)) / (1.0 - Ce * Cb));
    3738            0 :                     Cl = Ch + ((Ci * (Cc + Cb * Cf) + Cj * (Cf + Ce * Cc)) / (1.0 - Ce * Cb));
    3739              : 
    3740            0 :                     state.dataHeatBalFanSys->QRadSysSource(SurfNum) =
    3741            0 :                         EpsMdotCp * (WaterTempIn - Ck) / (1.0 + (EpsMdotCp * Cl / Surface(SurfNum).Area));
    3742              : 
    3743            0 :                 } else if (Surface(SurfNum).HeatTransferAlgorithm == DataSurfaces::HeatTransferModel::CondFD) {
    3744              : 
    3745            0 :                     state.dataHeatBalFanSys->QRadSysSource(SurfNum) = EpsMdotCp * (WaterTempIn - state.dataHeatBalFanSys->TCondFDSourceNode(SurfNum));
    3746              :                 }
    3747              : 
    3748            0 :                 if (Surface(SurfNum).ExtBoundCond > 0 && Surface(SurfNum).ExtBoundCond != SurfNum)
    3749            0 :                     state.dataHeatBalFanSys->QRadSysSource(Surface(SurfNum).ExtBoundCond) =
    3750            0 :                         state.dataHeatBalFanSys->QRadSysSource(SurfNum); // Also set the other side of an interzone
    3751              :             }
    3752              : 
    3753              :             // "Temperature Comparison" Cut-off:
    3754            0 :             for (int RadSurfNum = 1; RadSurfNum <= this->NumOfSurfaces; ++RadSurfNum) {
    3755              :                 // Check to see whether or not the system should really be running.  If
    3756              :                 // QRadSysSource is negative when we are in heating mode or QRadSysSource
    3757              :                 // is positive when we are in cooling mode, then the radiant system will
    3758              :                 // be doing the opposite of its intention.  In this case, the flow rate
    3759              :                 // is set to zero to avoid heating in cooling mode or cooling in heating
    3760              :                 // mode.
    3761            0 :                 int SurfNum = this->SurfacePtr(RadSurfNum);
    3762              : 
    3763            0 :                 if (((this->opMode == OpMode::Heat) && (state.dataHeatBalFanSys->QRadSysSource(SurfNum) <= 0.0)) ||
    3764            0 :                     ((this->opMode == OpMode::Cool) && (state.dataHeatBalFanSys->QRadSysSource(SurfNum) >= 0.0))) {
    3765            0 :                     WaterMassFlow = 0.0;
    3766            0 :                     if (this->opMode == OpMode::Heat) {
    3767            0 :                         SetComponentFlowRate(state, WaterMassFlow, this->HotWaterInNode, this->HotWaterOutNode, this->HWPlantLoc);
    3768              : 
    3769            0 :                     } else if (this->opMode == OpMode::Cool) {
    3770            0 :                         SetComponentFlowRate(state, WaterMassFlow, this->ColdWaterInNode, this->ColdWaterOutNode, this->CWPlantLoc);
    3771              :                     }
    3772            0 :                     this->WaterMassFlowRate = WaterMassFlow;
    3773            0 :                     this->opMode = OpMode::None;
    3774              : 
    3775            0 :                     for (int RadSurfNum2 = 1; RadSurfNum2 <= this->NumOfSurfaces; ++RadSurfNum2) {
    3776            0 :                         int SurfNum2 = this->SurfacePtr(RadSurfNum2);
    3777            0 :                         state.dataHeatBalFanSys->QRadSysSource(SurfNum2) = 0.0;
    3778            0 :                         if (Surface(SurfNum2).ExtBoundCond > 0 && Surface(SurfNum2).ExtBoundCond != SurfNum2)
    3779            0 :                             state.dataHeatBalFanSys->QRadSysSource(Surface(SurfNum2).ExtBoundCond) = 0.0; // Also zero the other side of an interzone
    3780              :                     }
    3781            0 :                     break; // outer do loop
    3782              :                 }
    3783              :             }
    3784              : 
    3785              :             // Condensation Cut-off:
    3786              :             // Check to see whether there are any surface temperatures within the radiant system that have
    3787              :             // dropped below the dew-point temperature.  If so, we need to shut off this radiant system.
    3788              :             // A safety parameter is added (hardwired parameter) to avoid getting too close to condensation
    3789              :             // conditions.
    3790            0 :             this->CondCausedShutDown = false;
    3791            0 :             DewPointTemp =
    3792            0 :                 PsyTdpFnWPb(state, state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).airHumRat, state.dataEnvrn->OutBaroPress);
    3793              : 
    3794            0 :             if ((this->opMode == OpMode::Cool) && (variableFlowDesignDataObject.condCtrlType == CondCtrlType::SimpleOff)) {
    3795              : 
    3796            0 :                 for (int RadSurfNum2 = 1; RadSurfNum2 <= this->NumOfSurfaces; ++RadSurfNum2) {
    3797            0 :                     if (state.dataHeatBalSurf->SurfInsideTempHist(1)(this->SurfacePtr(RadSurfNum2)) <
    3798            0 :                         (DewPointTemp + variableFlowDesignDataObject.CondDewPtDeltaT)) {
    3799              :                         // Condensation warning--must shut off radiant system
    3800            0 :                         this->CondCausedShutDown = true;
    3801            0 :                         WaterMassFlow = 0.0;
    3802            0 :                         this->opMode = OpMode::None;
    3803            0 :                         SetComponentFlowRate(state, WaterMassFlow, this->ColdWaterInNode, this->ColdWaterOutNode, this->CWPlantLoc);
    3804            0 :                         this->WaterMassFlowRate = WaterMassFlow;
    3805            0 :                         for (int RadSurfNum3 = 1; RadSurfNum3 <= this->NumOfSurfaces; ++RadSurfNum3) {
    3806            0 :                             int SurfNum2 = this->SurfacePtr(RadSurfNum3);
    3807            0 :                             state.dataHeatBalFanSys->QRadSysSource(SurfNum2) = 0.0;
    3808            0 :                             if (Surface(SurfNum2).ExtBoundCond > 0 && Surface(SurfNum2).ExtBoundCond != SurfNum2)
    3809            0 :                                 state.dataHeatBalFanSys->QRadSysSource(Surface(SurfNum2).ExtBoundCond) =
    3810              :                                     0.0; // Also zero the other side of an interzone
    3811              :                         }
    3812              :                         // Produce a warning message so that user knows the system was shut-off due to potential for condensation
    3813            0 :                         if (!state.dataGlobal->WarmupFlag) {
    3814            0 :                             if (this->CondErrIndex == 0) { // allow errors up to number of radiant systems
    3815            0 :                                 ShowWarningMessage(state, format("{} [{}]", cHydronicSystem, this->Name));
    3816            0 :                                 ShowContinueError(state,
    3817            0 :                                                   format("Surface [{}] temperature below dew-point temperature--potential for condensation exists",
    3818            0 :                                                          Surface(this->SurfacePtr(RadSurfNum2)).Name));
    3819            0 :                                 ShowContinueError(state, "Flow to the radiant system will be shut-off to avoid condensation");
    3820            0 :                                 ShowContinueError(state,
    3821            0 :                                                   format("Predicted radiant system surface temperature = {:.2R}",
    3822            0 :                                                          state.dataHeatBalSurf->SurfInsideTempHist(1)(this->SurfacePtr(RadSurfNum2))));
    3823            0 :                                 ShowContinueError(state,
    3824            0 :                                                   format("Zone dew-point temperature + safety delta T= {:.2R}",
    3825            0 :                                                          DewPointTemp + variableFlowDesignDataObject.CondDewPtDeltaT));
    3826            0 :                                 ShowContinueErrorTimeStamp(state, "");
    3827            0 :                                 ShowContinueError(state,
    3828            0 :                                                   format("Note that a {:.4R} C safety was chosen in the input for the shut-off criteria",
    3829              :                                                          variableFlowDesignDataObject.CondDewPtDeltaT));
    3830            0 :                                 ShowContinueError(state, "Note also that this affects all surfaces that are part of this radiant system");
    3831              :                             }
    3832            0 :                             ShowRecurringWarningErrorAtEnd(state,
    3833            0 :                                                            format("{} [{}] condensation shut-off occurrence continues.", cHydronicSystem, this->Name),
    3834            0 :                                                            this->CondErrIndex,
    3835              :                                                            DewPointTemp,
    3836              :                                                            DewPointTemp,
    3837              :                                                            _,
    3838              :                                                            "C",
    3839              :                                                            "C");
    3840              :                         }
    3841            0 :                         break; // outer do loop
    3842              :                     }
    3843              :                 }
    3844              : 
    3845            0 :             } else if ((this->opMode == OpMode::Cool) && (variableFlowDesignDataObject.condCtrlType == CondCtrlType::None)) {
    3846              : 
    3847            0 :                 for (int RadSurfNum2 = 1; RadSurfNum2 <= this->NumOfSurfaces; ++RadSurfNum2) {
    3848            0 :                     if (state.dataHeatBalSurf->SurfInsideTempHist(1)(this->SurfacePtr(RadSurfNum2)) < DewPointTemp) {
    3849              :                         // Condensation occurring but user does not want to shut radiant system off ever
    3850            0 :                         this->CondCausedShutDown = true;
    3851              :                     }
    3852              :                 }
    3853              : 
    3854            0 :             } else if ((this->opMode == OpMode::Cool) && (variableFlowDesignDataObject.condCtrlType == CondCtrlType::VariedOff)) {
    3855              : 
    3856            0 :                 LowestRadSurfTemp = 999.9;
    3857            0 :                 int CondSurfNum = 0;
    3858            0 :                 for (int RadSurfNum2 = 1; RadSurfNum2 <= this->NumOfSurfaces; ++RadSurfNum2) {
    3859            0 :                     if (state.dataHeatBalSurf->SurfInsideTempHist(1)(this->SurfacePtr(RadSurfNum2)) <
    3860            0 :                         (DewPointTemp + variableFlowDesignDataObject.CondDewPtDeltaT)) {
    3861            0 :                         if (state.dataHeatBalSurf->SurfInsideTempHist(1)(this->SurfacePtr(RadSurfNum2)) < LowestRadSurfTemp) {
    3862            0 :                             LowestRadSurfTemp = state.dataHeatBalSurf->SurfInsideTempHist(1)(this->SurfacePtr(RadSurfNum2));
    3863            0 :                             CondSurfNum = RadSurfNum2;
    3864              :                         }
    3865              :                     }
    3866              :                 }
    3867              : 
    3868            0 :                 if (CondSurfNum > 0) { // Condensation predicted so let's deal with it
    3869              :                     // Process here is: turn everything off and see what the resulting surface temperature is for
    3870              :                     // the surface that was causing the lowest temperature.  Then, interpolate to find the flow that
    3871              :                     // would still allow the system to operate without producing condensation.  Rerun the heat balance
    3872              :                     // and recheck for condensation.  If condensation still exists, shut everything down.  This avoids
    3873              :                     // excessive iteration and still makes an attempt to vary the flow rate.
    3874              :                     // First, shut everything off...
    3875            0 :                     FullWaterMassFlow = WaterMassFlow;
    3876            0 :                     WaterMassFlow = 0.0;
    3877            0 :                     SetComponentFlowRate(state, WaterMassFlow, this->ColdWaterInNode, this->ColdWaterOutNode, this->CWPlantLoc);
    3878            0 :                     this->WaterMassFlowRate = WaterMassFlow;
    3879            0 :                     for (int RadSurfNum3 = 1; RadSurfNum3 <= this->NumOfSurfaces; ++RadSurfNum3) {
    3880            0 :                         int SurfNum2 = this->SurfacePtr(RadSurfNum3);
    3881            0 :                         state.dataHeatBalFanSys->QRadSysSource(SurfNum2) = 0.0;
    3882            0 :                         if (Surface(SurfNum2).ExtBoundCond > 0 && Surface(SurfNum2).ExtBoundCond != SurfNum2)
    3883            0 :                             state.dataHeatBalFanSys->QRadSysSource(Surface(SurfNum2).ExtBoundCond) = 0.0; // Also zero the other side of an interzone
    3884              :                     }
    3885              :                     // Redo the heat balances since we have changed the heat source (set it to zero)
    3886            0 :                     HeatBalanceSurfaceManager::CalcHeatBalanceOutsideSurf(state, ZoneNum);
    3887            0 :                     HeatBalanceSurfaceManager::CalcHeatBalanceInsideSurf(state, ZoneNum);
    3888              :                     // Now check all of the surface temperatures.  If any potentially have condensation, leave the system off.
    3889            0 :                     for (int RadSurfNum2 = 1; RadSurfNum2 <= this->NumOfSurfaces; ++RadSurfNum2) {
    3890            0 :                         if (state.dataHeatBalSurf->SurfInsideTempHist(1)(this->SurfacePtr(RadSurfNum2)) <
    3891            0 :                             (DewPointTemp + variableFlowDesignDataObject.CondDewPtDeltaT)) {
    3892            0 :                             this->CondCausedShutDown = true;
    3893              :                         }
    3894              :                     }
    3895              :                     // If the system does not need to be shut down, then let's see if we can vary the flow based
    3896              :                     // on the lowest temperature surface from before.  This will use interpolation to try a new
    3897              :                     // flow rate.
    3898            0 :                     if (!this->CondCausedShutDown) {
    3899            0 :                         PredictedCondTemp = DewPointTemp + variableFlowDesignDataObject.CondDewPtDeltaT;
    3900            0 :                         ZeroFlowSurfTemp = state.dataHeatBalSurf->SurfInsideTempHist(1)(this->SurfacePtr(CondSurfNum));
    3901            0 :                         ReductionFrac = (ZeroFlowSurfTemp - PredictedCondTemp) / std::abs(ZeroFlowSurfTemp - LowestRadSurfTemp);
    3902            0 :                         if (ReductionFrac < 0.0) ReductionFrac = 0.0; // Shouldn't happen as the above check should have screened this out
    3903            0 :                         if (ReductionFrac > 1.0) ReductionFrac = 1.0; // Shouldn't happen either because condensation doesn't exist then
    3904            0 :                         WaterMassFlow = ReductionFrac * FullWaterMassFlow;
    3905            0 :                         SysWaterMassFlow = double(Zone(ZoneNum).Multiplier * Zone(ZoneNum).ListMultiplier) * WaterMassFlow;
    3906              :                         // Got a new reduced flow rate that should work...reset loop variable and resimulate the system
    3907            0 :                         SetComponentFlowRate(state, SysWaterMassFlow, this->ColdWaterInNode, this->ColdWaterOutNode, this->CWPlantLoc);
    3908            0 :                         this->WaterMassFlowRate = SysWaterMassFlow;
    3909              : 
    3910              :                         // Go through all of the surfaces again with the new flow rate...
    3911            0 :                         for (int RadSurfNum3 = 1; RadSurfNum3 <= this->NumOfSurfaces; ++RadSurfNum3) {
    3912            0 :                             int SurfNum = this->SurfacePtr(RadSurfNum3);
    3913              :                             // Determine the heat exchanger "effectiveness" term
    3914              : 
    3915            0 :                             EpsMdotCp = calculateHXEffectivenessTerm(state,
    3916              :                                                                      SurfNum,
    3917              :                                                                      WaterTempIn,
    3918              :                                                                      WaterMassFlow,
    3919            0 :                                                                      this->SurfaceFrac(RadSurfNum3),
    3920            0 :                                                                      this->NumCircuits(RadSurfNum3),
    3921              :                                                                      this->DesignObjectPtr,
    3922              :                                                                      typeOfRadiantSystem);
    3923              : 
    3924            0 :                             int ConstrNum = Surface(SurfNum).Construction;
    3925            0 :                             auto const &thisConstruct = state.dataConstruction->Construct(ConstrNum);
    3926            0 :                             if (Surface(SurfNum).HeatTransferAlgorithm == DataSurfaces::HeatTransferModel::CTF) {
    3927              :                                 // For documentation on coefficients, see code earlier in this subroutine
    3928            0 :                                 Ca = state.dataHeatBalFanSys->RadSysTiHBConstCoef(SurfNum);
    3929            0 :                                 Cb = state.dataHeatBalFanSys->RadSysTiHBToutCoef(SurfNum);
    3930            0 :                                 Cc = state.dataHeatBalFanSys->RadSysTiHBQsrcCoef(SurfNum);
    3931            0 :                                 Cd = state.dataHeatBalFanSys->RadSysToHBConstCoef(SurfNum);
    3932            0 :                                 Ce = state.dataHeatBalFanSys->RadSysToHBTinCoef(SurfNum);
    3933            0 :                                 Cf = state.dataHeatBalFanSys->RadSysToHBQsrcCoef(SurfNum);
    3934            0 :                                 Cg = state.dataHeatBalFanSys->CTFTsrcConstPart(SurfNum);
    3935            0 :                                 Ch = thisConstruct.CTFTSourceQ[0];
    3936            0 :                                 Ci = thisConstruct.CTFTSourceIn[0];
    3937            0 :                                 Cj = thisConstruct.CTFTSourceOut[0];
    3938            0 :                                 Ck = Cg + ((Ci * (Ca + Cb * Cd) + Cj * (Cd + Ce * Ca)) / (1.0 - Ce * Cb));
    3939            0 :                                 Cl = Ch + ((Ci * (Cc + Cb * Cf) + Cj * (Cf + Ce * Cc)) / (1.0 - Ce * Cb));
    3940            0 :                                 state.dataHeatBalFanSys->QRadSysSource(SurfNum) =
    3941            0 :                                     EpsMdotCp * (WaterTempIn - Ck) / (1.0 + (EpsMdotCp * Cl / Surface(SurfNum).Area));
    3942            0 :                             } else if (Surface(SurfNum).HeatTransferAlgorithm == DataSurfaces::HeatTransferModel::CondFD) {
    3943            0 :                                 state.dataHeatBalFanSys->QRadSysSource(SurfNum) =
    3944            0 :                                     EpsMdotCp * (WaterTempIn - state.dataHeatBalFanSys->TCondFDSourceNode(SurfNum));
    3945              :                             }
    3946            0 :                             if (Surface(SurfNum).ExtBoundCond > 0 && Surface(SurfNum).ExtBoundCond != SurfNum)
    3947            0 :                                 state.dataHeatBalFanSys->QRadSysSource(Surface(SurfNum).ExtBoundCond) =
    3948            0 :                                     state.dataHeatBalFanSys->QRadSysSource(SurfNum); // Also set the other side of an interzone
    3949              :                         }
    3950              : 
    3951              :                         // Redo the heat balances since we have changed the heat source
    3952            0 :                         HeatBalanceSurfaceManager::CalcHeatBalanceOutsideSurf(state, ZoneNum);
    3953            0 :                         HeatBalanceSurfaceManager::CalcHeatBalanceInsideSurf(state, ZoneNum);
    3954              : 
    3955              :                         // Check for condensation one more time.  If no condensation, we are done.  If there is
    3956              :                         // condensation, shut things down and be done.
    3957            0 :                         for (int RadSurfNum2 = 1; RadSurfNum2 <= this->NumOfSurfaces; ++RadSurfNum2) {
    3958            0 :                             if (this->CondCausedShutDown) break;
    3959            0 :                             if (state.dataHeatBalSurf->SurfInsideTempHist(1)(this->SurfacePtr(RadSurfNum2)) < (PredictedCondTemp)) {
    3960              :                                 // Condensation still present--must shut off radiant system
    3961            0 :                                 this->CondCausedShutDown = true;
    3962            0 :                                 WaterMassFlow = 0.0;
    3963            0 :                                 this->opMode = OpMode::None;
    3964            0 :                                 SetComponentFlowRate(state, WaterMassFlow, this->ColdWaterInNode, this->ColdWaterOutNode, this->CWPlantLoc);
    3965            0 :                                 this->WaterMassFlowRate = WaterMassFlow;
    3966            0 :                                 for (int RadSurfNum3 = 1; RadSurfNum3 <= this->NumOfSurfaces; ++RadSurfNum3) {
    3967            0 :                                     int SurfNum2 = this->SurfacePtr(RadSurfNum3);
    3968            0 :                                     state.dataHeatBalFanSys->QRadSysSource(SurfNum2) = 0.0;
    3969            0 :                                     if (Surface(SurfNum2).ExtBoundCond > 0 && Surface(SurfNum2).ExtBoundCond != SurfNum2)
    3970            0 :                                         state.dataHeatBalFanSys->QRadSysSource(Surface(SurfNum2).ExtBoundCond) =
    3971              :                                             0.0; // Also zero the other side of an interzone
    3972              :                                 }
    3973              :                             }
    3974              :                         }
    3975              :                     }
    3976              : 
    3977            0 :                     if (this->CondCausedShutDown) {
    3978              :                         // Produce a warning message so that user knows the system was shut-off due to potential for condensation
    3979            0 :                         if (!state.dataGlobal->WarmupFlag) {
    3980            0 :                             if (this->CondErrIndex == 0) { // allow errors up to number of radiant systems
    3981            0 :                                 ShowWarningMessage(state, format("{} [{}]", cHydronicSystem, this->Name));
    3982            0 :                                 ShowContinueError(state,
    3983            0 :                                                   format("Surface [{}] temperature below dew-point temperature--potential for condensation exists",
    3984            0 :                                                          Surface(this->SurfacePtr(CondSurfNum)).Name));
    3985            0 :                                 ShowContinueError(state, "Flow to the radiant system will be shut-off to avoid condensation");
    3986            0 :                                 ShowContinueError(state,
    3987            0 :                                                   format("Predicted radiant system surface temperature = {:.2R}",
    3988            0 :                                                          state.dataHeatBalSurf->SurfInsideTempHist(1)(this->SurfacePtr(CondSurfNum))));
    3989            0 :                                 ShowContinueError(state,
    3990            0 :                                                   format("Zone dew-point temperature + safety delta T= {:.2R}",
    3991            0 :                                                          DewPointTemp + variableFlowDesignDataObject.CondDewPtDeltaT));
    3992            0 :                                 ShowContinueErrorTimeStamp(state, "");
    3993            0 :                                 ShowContinueError(state,
    3994            0 :                                                   format("Note that a {:.4R} C safety was chosen in the input for the shut-off criteria",
    3995              :                                                          variableFlowDesignDataObject.CondDewPtDeltaT));
    3996            0 :                                 ShowContinueError(state, "Note also that this affects all surfaces that are part of this radiant system");
    3997              :                             }
    3998            0 :                             ShowRecurringWarningErrorAtEnd(state,
    3999            0 :                                                            format("{} [{}] condensation shut-off occurrence continues.", cHydronicSystem, this->Name),
    4000            0 :                                                            this->CondErrIndex,
    4001              :                                                            DewPointTemp,
    4002              :                                                            DewPointTemp,
    4003              :                                                            _,
    4004              :                                                            "C",
    4005              :                                                            "C");
    4006              :                         }
    4007              :                     }
    4008              :                 } // Condensation Predicted in Variable Shut-Off Control Type
    4009              :             }     // In cooling mode and one of the condensation control types
    4010              :         }         // There was a non-zero flow
    4011              : 
    4012              :         // Now that we have the source/sink term, we must redo the heat balances to obtain
    4013              :         // the new SumHATsurf value for the zone.  Note that the difference between the new
    4014              :         // SumHATsurf and the value originally calculated by the heat balance with a zero
    4015              :         // source for all radiant systems in the zone is the load met by the system (approximately).
    4016            0 :         HeatBalanceSurfaceManager::CalcHeatBalanceOutsideSurf(state, ZoneNum);
    4017            0 :         HeatBalanceSurfaceManager::CalcHeatBalanceInsideSurf(state, ZoneNum);
    4018              : 
    4019            0 :         LoadMet = state.dataHeatBal->Zone(ZoneNum).sumHATsurf(state) - this->ZeroLTRSourceSumHATsurf;
    4020            0 :     }
    4021              : 
    4022            2 :     void ConstantFlowRadiantSystemData::calculateLowTemperatureRadiantSystem(EnergyPlusData &state,
    4023              :                                                                              Real64 &LoadMet) // load met by the radiant system, in Watts
    4024              :     {
    4025              : 
    4026              :         // SUBROUTINE INFORMATION:
    4027              :         //       AUTHOR         Rick Strand
    4028              :         //       DATE WRITTEN   August 2003
    4029              : 
    4030              :         // PURPOSE OF THIS SUBROUTINE:
    4031              :         // This subroutine does all of the stuff that is necessary to simulate
    4032              :         // a constant flow low temperature hydronic radiant heating/cooling system.
    4033              :         // Calls are made to appropriate subroutines either in this module or
    4034              :         // outside of it.
    4035              : 
    4036              :         // METHODOLOGY EMPLOYED:
    4037              :         // Similar in many aspects to the hydronic (variable flow) radiant system
    4038              :         // except that flow rate through the radiant system is constant (based on
    4039              :         // the user schedule) and the inlet temperature is varied by injecting
    4040              :         // more or less fluid from the main loop to achieve the desired inlet
    4041              :         // temperature.
    4042              : 
    4043              :         // REFERENCES:
    4044              :         // Other EnergyPlus modules
    4045              :         // IBLAST-QTF research program, completed in January 1995 (unreleased)
    4046              :         // Strand, R.K. 1995. "Heat Source Transfer Functions and Their Application to
    4047              :         //   Low Temperature Radiant Heating Systems", Ph.D. dissertation, University
    4048              :         //   of Illinois at Urbana-Champaign, Department of Mechanical and Industrial
    4049              :         //   Engineering.
    4050              :         // Seem, J.E. 1986. "Heat Transfer in Buildings", Ph.D. dissertation, University
    4051              :         //   of Wisconsin-Madison.
    4052              : 
    4053              :         // Using/Aliasing
    4054              :         using DataHeatBalance::ZoneData;
    4055              :         using HVAC::SmallLoad;
    4056              :         using PlantUtilities::SetComponentFlowRate;
    4057              : 
    4058              :         // SUBROUTINE PARAMETER DEFINITIONS:
    4059            2 :         Real64 constexpr LowCpFluidValue(100.0); // lowest allowed Cp fluid value (to avoid dividing by zero) [J/kg-K]
    4060            2 :         constexpr std::string_view RoutineName("CalcLowTempCFloRadiantSystem");
    4061              : 
    4062              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    4063              :         Real64 CpFluid;         // Specific heat of the fluid in the radiant system
    4064              :         Real64 InjectFlowRate;  // Calculated injection flow rate that will meet the inlet temperature requirement
    4065              :         Real64 OffTempCool;     // temperature at which the cooling shuts down
    4066              :         Real64 OffTempHeat;     // temperature at which the heating shuts down
    4067              :         Real64 PumpPartLoadRat; // Pump part load ratio (based on user schedule, or 1.0 for no schedule)
    4068              :         Real64 PumpTempRise;    // Temperature rise of the fluid as it passes through the pump
    4069              :         Real64 RadInTemp;       // "Desired" radiant system water inlet temperature [Celsius]
    4070              :         Real64 SetPointTemp;    // temperature that will be used to control the radiant system [Celsius]
    4071              :         Real64 SetPointTempHi;  // Current high point in setpoint temperature range
    4072              :         Real64 SetPointTempLo;  // Current low point in setpoint temperature range
    4073              :         Real64 ShaftPower;      // Amount of power expended at the pump shaft
    4074              :         bool SysRunning;        // TRUE when the system is running
    4075              :         Real64 SysWaterInTemp;  // Fluid temperature supplied from the loop
    4076              :         Real64 WaterTempHi;     // Current high point in water temperature range
    4077              :         Real64 WaterTempLo;     // Current low point in water temperature range
    4078              :         Real64 mdot;            // local temporary for water mass flow rate kg/s
    4079              : 
    4080              :         ConstantFlowRadDesignData ConstantFlowDesignDataObject =                   // Once again, is this supposed to be a deep copy?
    4081            2 :             state.dataLowTempRadSys->CflowRadiantSysDesign(this->DesignObjectPtr); // Contains the data for variable flow hydronic systems
    4082              : 
    4083              :         // initialize local variables
    4084            2 :         SysRunning = true; // default to running and turn off only if not running
    4085            2 :         state.dataLowTempRadSys->VarOffCond = false;
    4086              : 
    4087            2 :         if (this->availSched->getCurrentVal() <= 0) SysRunning = false;
    4088              : 
    4089            2 :         if (SysRunning) { // Unit is probably on-->this section is intended to control the water
    4090              :             // mass flow rate being sent to the radiant system
    4091              : 
    4092              :             // Set the current setpoint temperature (same procedure for either heating or cooling)
    4093              : 
    4094            2 :             SetPointTemp = this->setRadiantSystemControlTemperature(state, ConstantFlowDesignDataObject.ConstFlowControlType);
    4095              : 
    4096              :             // Avoid problems when there is no heating or cooling control because the system only cools or heats
    4097            2 :             if (this->hotCtrlHiTempSched != nullptr) {
    4098            2 :                 OffTempHeat = this->hotCtrlHiTempSched->getCurrentVal();
    4099              :             } else {
    4100            0 :                 OffTempHeat = state.dataLowTempRadSys->LowTempHeating;
    4101              :             }
    4102            2 :             if (this->coldCtrlLoTempSched != nullptr) {
    4103            2 :                 OffTempCool = this->coldCtrlLoTempSched->getCurrentVal();
    4104              :             } else {
    4105            0 :                 OffTempCool = state.dataLowTempRadSys->HighTempCooling;
    4106              :             }
    4107              : 
    4108            2 :             if (SetPointTemp < OffTempHeat && this->HeatingSystem) { // Heating mode
    4109            0 :                 this->opMode = OpMode::Heat;
    4110            2 :             } else if (SetPointTemp > OffTempCool && this->CoolingSystem) { // Cooling mode
    4111            0 :                 this->opMode = OpMode::Cool;
    4112              :             }
    4113              : 
    4114            2 :             this->setOperatingModeBasedOnChangeoverDelay(state);
    4115              : 
    4116              :             // Now actually decide what to do based on the setpoint temperature in relation to the control temperatures
    4117            2 :             if (this->opMode == OpMode::Heat) { // HEATING MODE
    4118              : 
    4119            0 :                 this->WaterMassFlowRate = this->HotWaterMassFlowRate;
    4120              : 
    4121            0 :                 if (!this->HeatingSystem) {
    4122              : 
    4123            0 :                     SysRunning = false; // Can't heat unless it's a heating system
    4124              : 
    4125              :                 } else { // It is a heating system so set all of the values for controls
    4126              : 
    4127            0 :                     SetPointTempHi = this->hotCtrlHiTempSched->getCurrentVal();
    4128            0 :                     SetPointTempLo = this->hotCtrlLoTempSched->getCurrentVal();
    4129            0 :                     if (SetPointTempHi < SetPointTempLo) {
    4130            0 :                         ShowSevereError(state, format("Heating setpoint temperature mismatch in{}", this->Name));
    4131            0 :                         ShowContinueError(state, "High setpoint temperature is less than low setpoint temperature--check your schedule input");
    4132            0 :                         ShowFatalError(state, "Preceding condition causes termination.");
    4133              :                     }
    4134              : 
    4135            0 :                     WaterTempHi = this->hotWaterHiTempSched->getCurrentVal();
    4136            0 :                     WaterTempLo = this->hotWaterLoTempSched->getCurrentVal();
    4137            0 :                     if (WaterTempHi < WaterTempLo) {
    4138            0 :                         ShowSevereError(state, format("Heating water temperature mismatch in{}", this->Name));
    4139            0 :                         ShowContinueError(state, "High water temperature is less than low water temperature--check your schedule input");
    4140            0 :                         ShowFatalError(state, "Preceding condition causes termination.");
    4141              :                     }
    4142              : 
    4143            0 :                     if (SetPointTemp >= SetPointTempHi) {
    4144              :                         // System is above high heating setpoint so we should be able to turn the system off
    4145            0 :                         RadInTemp = WaterTempLo;
    4146            0 :                         SysRunning = false;
    4147            0 :                     } else if (SetPointTemp <= SetPointTempLo) {
    4148              :                         // System is running with its highest inlet temperature
    4149            0 :                         RadInTemp = WaterTempHi;
    4150              :                     } else {
    4151              :                         // Interpolate to obtain the current radiant system inlet temperature
    4152            0 :                         RadInTemp = WaterTempHi - (WaterTempHi - WaterTempLo) * (SetPointTemp - SetPointTempLo) / (SetPointTempHi - SetPointTempLo);
    4153              :                     }
    4154              :                 }
    4155              : 
    4156            2 :             } else if (this->opMode == OpMode::Cool) { // COOLING MODE
    4157              : 
    4158            0 :                 this->WaterMassFlowRate = this->ChWaterMassFlowRate;
    4159              : 
    4160            0 :                 if (!this->CoolingSystem) {
    4161              : 
    4162            0 :                     SysRunning = false; // Can't cool unless it's a cooling system
    4163              : 
    4164              :                 } else { // It is a cooling system so set all of the values for controls
    4165              : 
    4166            0 :                     SetPointTempHi = this->coldCtrlHiTempSched->getCurrentVal();
    4167            0 :                     SetPointTempLo = this->coldCtrlLoTempSched->getCurrentVal();
    4168            0 :                     if (SetPointTempHi < SetPointTempLo) {
    4169            0 :                         ShowSevereError(state, format("Cooling setpoint temperature mismatch in{}", this->Name));
    4170            0 :                         ShowContinueError(state, "High setpoint temperature is less than low setpoint temperature--check your schedule input");
    4171            0 :                         ShowFatalError(state, "Preceding condition causes termination.");
    4172              :                     }
    4173              : 
    4174            0 :                     WaterTempHi = this->coldWaterHiTempSched->getCurrentVal();
    4175            0 :                     WaterTempLo = this->coldWaterLoTempSched->getCurrentVal();
    4176            0 :                     if (WaterTempHi < WaterTempLo) {
    4177            0 :                         ShowSevereError(state, format("Cooling water temperature mismatch in{}", this->Name));
    4178            0 :                         ShowContinueError(state, "High water temperature is less than low water temperature--check your schedule input");
    4179            0 :                         ShowFatalError(state, "Preceding condition causes termination.");
    4180              :                     }
    4181              : 
    4182            0 :                     if (SetPointTemp <= SetPointTempLo) {
    4183              :                         // System is below low cooling setpoint so we should be able to turn the system off
    4184            0 :                         RadInTemp = WaterTempHi;
    4185            0 :                         SysRunning = false;
    4186            0 :                     } else if (SetPointTemp >= SetPointTempHi) {
    4187              :                         // System is running with its lowest inlet temperature
    4188            0 :                         RadInTemp = WaterTempLo;
    4189              :                     } else {
    4190              :                         // Interpolate to obtain the current radiant system inlet temperature
    4191            0 :                         RadInTemp = WaterTempHi - (WaterTempHi - WaterTempLo) * (SetPointTemp - SetPointTempLo) / (SetPointTempHi - SetPointTempLo);
    4192              :                     }
    4193              :                 }
    4194              : 
    4195              :             } else { // System is not running because the setpoint temperature is in the "deadband"
    4196              : 
    4197            2 :                 RadInTemp = SetPointTemp;
    4198            2 :                 SysRunning = false;
    4199              :             }
    4200              :         }
    4201              : 
    4202            2 :         if (SysRunning) {
    4203            0 :             CpFluid = this->water->getSpecificHeat(state, RadInTemp, RoutineName);
    4204              :         }
    4205              : 
    4206            2 :         if ((!SysRunning) || (CpFluid < LowCpFluidValue)) {
    4207              :             // Unit is off or has no load upon it OR CpFluid value is "zero" so
    4208              :             // set the flow rates to zero and then simulate the components with
    4209              :             // the no flow conditions
    4210            2 :             this->opMode = OpMode::None;
    4211            2 :             this->WaterMassFlowRate = 0.0;
    4212            2 :             this->WaterInjectionRate = 0.0;
    4213            2 :             this->WaterRecircRate = 0.0;
    4214            2 :             this->HeatPower = 0.0;
    4215            2 :             this->CoolPower = 0.0;
    4216            2 :             this->PumpPower = 0.0;
    4217            2 :             this->PumpMassFlowRate = 0.0;
    4218            2 :             this->PumpHeattoFluid = 0.0;
    4219              : 
    4220            2 :             for (int SurfNum = 1; SurfNum <= this->NumOfSurfaces; ++SurfNum) {
    4221            0 :                 int SurfNum2 = this->SurfacePtr(SurfNum);
    4222            0 :                 auto &surface = state.dataSurface->Surface(SurfNum2);
    4223            0 :                 state.dataHeatBalFanSys->QRadSysSource(SurfNum2) = 0.0;
    4224            0 :                 if (surface.ExtBoundCond > 0 && surface.ExtBoundCond != SurfNum2)
    4225            0 :                     state.dataHeatBalFanSys->QRadSysSource(surface.ExtBoundCond) = 0.0; // Also zero the other side of an interzone
    4226              :             }
    4227              : 
    4228              :             // turn off flow requests made during init because it is not actually running
    4229            2 :             if (this->CWPlantLoc.loopNum > 0) {
    4230            0 :                 mdot = 0.0;
    4231            0 :                 SetComponentFlowRate(state, mdot, this->ColdWaterInNode, this->ColdWaterOutNode, this->CWPlantLoc);
    4232              :             }
    4233            2 :             if (this->HWPlantLoc.loopNum > 0) {
    4234            0 :                 mdot = 0.0;
    4235            0 :                 SetComponentFlowRate(state, mdot, this->HotWaterInNode, this->HotWaterOutNode, this->HWPlantLoc);
    4236              :             }
    4237            2 :         } else {            // (SysRunning) so simulate the system...
    4238              :             bool Iteration; // FALSE when a normal solution, TRUE when it is a solution where we must also find the inlet temp
    4239              :             int LoopInNode; // Node on the loop that is the inlet to the constant flow radiant system
    4240              : 
    4241              :             // Determine pump flow rate and pump heat addition
    4242            0 :             this->PumpMassFlowRate = this->WaterMassFlowRate; // Set in InitLowTempRadiantSystem
    4243            0 :             PumpPartLoadRat = (this->volFlowSched != nullptr) ? this->volFlowSched->getCurrentVal() : 1.0;
    4244              : 
    4245            0 :             this->PumpPower = PumpPartLoadRat * this->NomPowerUse;
    4246            0 :             ShaftPower = this->PumpPower * ConstantFlowDesignDataObject.MotorEffic;
    4247              :             // This adds the pump heat based on User input for the pump (same as in Pump module)
    4248              :             // We assume that all of the heat ends up in the fluid eventually since this is a closed loop.
    4249            0 :             this->PumpHeattoFluid = ShaftPower + ((this->PumpPower - ShaftPower) * ConstantFlowDesignDataObject.FracMotorLossToFluid);
    4250            0 :             if (this->PumpMassFlowRate > 0.0) {
    4251            0 :                 PumpTempRise = this->PumpHeattoFluid / (this->PumpMassFlowRate * CpFluid);
    4252              :             } else {
    4253            0 :                 PumpTempRise = 0.0;
    4254              :             }
    4255              : 
    4256            0 :             state.dataLowTempRadSys->LoopReqTemp =
    4257            0 :                 RadInTemp - PumpTempRise; // Temperature required at the inlet of the pump to meet the temperature request
    4258              : 
    4259            0 :             if (this->opMode == OpMode::Heat) {
    4260              : 
    4261              :                 // in heating mode so shut down cold water flow request
    4262            0 :                 if (this->CWPlantLoc.loopNum > 0) {
    4263            0 :                     mdot = 0.0;
    4264            0 :                     SetComponentFlowRate(state, mdot, this->ColdWaterInNode, this->ColdWaterOutNode, this->CWPlantLoc);
    4265              :                 }
    4266            0 :                 LoopInNode = this->HotWaterInNode;
    4267            0 :                 auto const &hotNode = state.dataLoopNodes->Node(LoopInNode);
    4268            0 :                 SysWaterInTemp = hotNode.Temp;
    4269            0 :                 Iteration = false;
    4270              : 
    4271            0 :                 if ((SysWaterInTemp >= state.dataLowTempRadSys->LoopReqTemp) && (hotNode.MassFlowRateMaxAvail >= this->WaterMassFlowRate)) {
    4272              :                     // Case 1: Adequate temperature and flow
    4273              :                     // Best condition--loop inlet temperature greater than requested and we have enough flow.
    4274              :                     // So, proceed assuming the RadInTemp requested by the controls and then figure out the
    4275              :                     // mixing after the outlet radiant temperature is calculated.
    4276            0 :                     this->WaterInletTemp = RadInTemp;
    4277            0 :                     this->calculateLowTemperatureRadiantSystemComponents(state, LoopInNode, Iteration, LoadMet, SystemType::ConstantFlow);
    4278              : 
    4279              :                     // We now have inlet and outlet temperatures--we still need to set the flow rates
    4280            0 :                     if ((SysWaterInTemp - this->WaterOutletTemp) != 0.0) { // protect divide by zero
    4281            0 :                         this->WaterInjectionRate =
    4282            0 :                             (this->WaterMassFlowRate * (this->WaterInletTemp - this->WaterOutletTemp) / (SysWaterInTemp - this->WaterOutletTemp)) -
    4283            0 :                             (this->PumpHeattoFluid / (CpFluid * (SysWaterInTemp - this->WaterOutletTemp)));
    4284              :                     } else {
    4285            0 :                         this->WaterInjectionRate = this->WaterMassFlowRate;
    4286              :                     }
    4287            0 :                     this->WaterRecircRate = this->WaterMassFlowRate - this->WaterInjectionRate;
    4288              : 
    4289            0 :                 } else if ((SysWaterInTemp < state.dataLowTempRadSys->LoopReqTemp) && (hotNode.MassFlowRateMaxAvail >= this->WaterMassFlowRate)) {
    4290              :                     // Case 2: Adequate flow but temperature too low
    4291              :                     // Only thing to do is to reset the inlet temperature and assume that the loop will supply
    4292              :                     // the entire flow to the component (no recirculation but potentially some bypass for the
    4293              :                     // overall loop).  There is no way we can meet the control temperature so don't even try.
    4294            0 :                     this->WaterInletTemp = SysWaterInTemp + PumpTempRise;
    4295            0 :                     this->calculateLowTemperatureRadiantSystemComponents(state, LoopInNode, Iteration, LoadMet, SystemType::ConstantFlow);
    4296              : 
    4297              :                     // We now have inlet and outlet temperatures--we still need to set the flow rates
    4298            0 :                     if ((SysWaterInTemp - this->WaterOutletTemp) != 0.0) { // protect divide by zero
    4299            0 :                         this->WaterInjectionRate =
    4300            0 :                             (this->WaterMassFlowRate * (this->WaterInletTemp - this->WaterOutletTemp) / (SysWaterInTemp - this->WaterOutletTemp)) -
    4301            0 :                             (this->PumpHeattoFluid / (CpFluid * (SysWaterInTemp - this->WaterOutletTemp)));
    4302              :                     } else {
    4303            0 :                         this->WaterInjectionRate = this->WaterMassFlowRate;
    4304              :                     }
    4305            0 :                     if (this->WaterInjectionRate > this->WaterMassFlowRate) this->WaterInjectionRate = this->WaterMassFlowRate;
    4306            0 :                     this->WaterRecircRate = 0.0; // by definition
    4307              : 
    4308            0 :                 } else if ((SysWaterInTemp >= state.dataLowTempRadSys->LoopReqTemp) && (hotNode.MassFlowRateMaxAvail < this->WaterMassFlowRate)) {
    4309              :                     // Case 3: Adequate temperature but loop flow is less than component flow
    4310              :                     // This case might work out, but there is no guarantee that there is enough loop flow to
    4311              :                     // mix with the recirculation flow and still provide a high enough temperature.  First
    4312              :                     // step is to try the inlet temperature and flow rate as in Case 1.  If we can obtain
    4313              :                     // the proper temperature inlet to the radiant system, then we are done.  If not, we
    4314              :                     // have to repeat the solution for an unknown inlet temperature and a known recirculation
    4315              :                     // rate.
    4316            0 :                     this->WaterInletTemp = RadInTemp;
    4317            0 :                     this->calculateLowTemperatureRadiantSystemComponents(state, LoopInNode, Iteration, LoadMet, SystemType::ConstantFlow);
    4318              : 
    4319              :                     // Now see if we can really get that desired into temperature (RadInTemp) by solving
    4320              :                     // for the flow that is injected from the loop.  A heat balance for the mixer that relates
    4321              :                     // the important quantities is:
    4322              :                     //   Mdotradsys*Cp*Tradsysin = Mdotloop*Cp*Tloop + (Mdotradsys-Mdotloop)*Cp*Tradsysout + PumpHeat
    4323              :                     // or rearranging to get the injection flow (Mdotloop):
    4324              :                     //   Mdotloop = Mdotcomp*(Tradsysin-Tradsysout)/(Tloop-Tradsysout) - PumpHeat/(Cp*(Tloop-Tradsysout))
    4325              :                     // If Mdotloop from this equation is greater that the loop flow rate (Node%MassFlowRate),
    4326              :                     // then we cannot meet the inlet temperature and we have to "iterate" through the
    4327              :                     // alternate solution.
    4328            0 :                     if ((SysWaterInTemp - this->WaterOutletTemp) != 0.0) { // protect divide by zero
    4329            0 :                         InjectFlowRate =
    4330            0 :                             (this->WaterMassFlowRate * (this->WaterInletTemp - this->WaterOutletTemp) / (SysWaterInTemp - this->WaterOutletTemp)) -
    4331            0 :                             (this->PumpHeattoFluid / (CpFluid * (SysWaterInTemp - this->WaterOutletTemp)));
    4332              :                     } else {
    4333            0 :                         InjectFlowRate = this->WaterMassFlowRate;
    4334              :                     }
    4335            0 :                     if (InjectFlowRate > hotNode.MassFlowRateMaxAvail) {
    4336              :                         // We didn't have enough flow from the loop to meet our inlet temperature request.
    4337              :                         // So, set the injection rate to the loop flow and calculate the recirculation flow.
    4338              :                         // Then, resimulate the radiant system using these values (it will obtain the actual
    4339              :                         // inlet temperature that results from this).
    4340            0 :                         this->WaterInjectionRate = hotNode.MassFlowRateMaxAvail;
    4341            0 :                         this->WaterRecircRate = this->WaterMassFlowRate - this->WaterInjectionRate;
    4342            0 :                         this->WaterInletTemp = SysWaterInTemp + PumpTempRise;
    4343            0 :                         Iteration = true;
    4344            0 :                         this->calculateLowTemperatureRadiantSystemComponents(state, LoopInNode, Iteration, LoadMet, SystemType::ConstantFlow);
    4345              :                     } else {
    4346            0 :                         this->WaterInjectionRate = InjectFlowRate;
    4347            0 :                         this->WaterRecircRate = this->WaterMassFlowRate - this->WaterInjectionRate;
    4348              :                     }
    4349              : 
    4350            0 :                 } else if ((SysWaterInTemp < state.dataLowTempRadSys->LoopReqTemp) && (hotNode.MassFlowRateMaxAvail < this->WaterMassFlowRate)) {
    4351              :                     // Case 4: Temperature too low and loop flow is less than component flow
    4352              :                     // Worst condition--can't meet the temperature request at all.  Only thing to do is to
    4353              :                     // set the loop flow and recirculation rate (known) and solve for the inlet temperature
    4354              :                     // using the "iteration" solution scheme from "Case 3B" above
    4355            0 :                     this->WaterInjectionRate = hotNode.MassFlowRateMaxAvail;
    4356            0 :                     this->WaterRecircRate = this->WaterMassFlowRate - this->WaterInjectionRate;
    4357            0 :                     this->WaterInletTemp = SysWaterInTemp + PumpTempRise;
    4358            0 :                     Iteration = true;
    4359            0 :                     this->calculateLowTemperatureRadiantSystemComponents(state, LoopInNode, Iteration, LoadMet, SystemType::ConstantFlow);
    4360              :                 }
    4361              : 
    4362            0 :             } else if (this->opMode == OpMode::Cool) {
    4363              : 
    4364              :                 // in cooling mode so shut down heating water flow request
    4365            0 :                 if (this->HWPlantLoc.loopNum > 0) {
    4366            0 :                     mdot = 0.0;
    4367            0 :                     SetComponentFlowRate(state, mdot, this->HotWaterInNode, this->HotWaterOutNode, this->HWPlantLoc);
    4368              :                 }
    4369            0 :                 LoopInNode = this->ColdWaterInNode;
    4370            0 :                 auto const &coldNode = state.dataLoopNodes->Node(LoopInNode);
    4371            0 :                 SysWaterInTemp = coldNode.Temp;
    4372            0 :                 state.dataLowTempRadSys->CFloCondIterNum = 1;
    4373            0 :                 while ((state.dataLowTempRadSys->CFloCondIterNum <= 1) ||
    4374            0 :                        ((state.dataLowTempRadSys->CFloCondIterNum <= 2) && (ConstantFlowDesignDataObject.condCtrlType == CondCtrlType::VariedOff) &&
    4375            0 :                         (state.dataLowTempRadSys->VarOffCond))) {
    4376            0 :                     Iteration = false;
    4377              : 
    4378            0 :                     if ((SysWaterInTemp <= state.dataLowTempRadSys->LoopReqTemp) && (coldNode.MassFlowRateMaxAvail >= this->WaterMassFlowRate)) {
    4379              :                         // Case 1: Adequate temperature and flow
    4380              :                         // Best condition--loop inlet temperature lower than requested and we have enough flow.
    4381              :                         // So, proceed assuming the RadInTemp requested by the controls and then figure out the
    4382              :                         // mixing after the outlet radiant temperature is calculated.
    4383              : 
    4384              :                         // This condition can also happen when state.dataLowTempRadSys->LoopReqTemp has been reset  to dewpoint for condensation
    4385              :                         // control
    4386            0 :                         if (!state.dataLowTempRadSys->VarOffCond) {
    4387            0 :                             this->WaterInletTemp = RadInTemp;
    4388              :                         } else {
    4389            0 :                             this->WaterInletTemp = state.dataLowTempRadSys->LoopReqTemp;
    4390              :                         }
    4391            0 :                         this->calculateLowTemperatureRadiantSystemComponents(state, LoopInNode, Iteration, LoadMet, SystemType::ConstantFlow);
    4392              : 
    4393              :                         // We now have inlet and outlet temperatures--we still need to set the flow rates
    4394            0 :                         if ((SysWaterInTemp - this->WaterOutletTemp) != 0.0) { // protect div by zero
    4395            0 :                             this->WaterInjectionRate = (this->WaterMassFlowRate * (this->WaterInletTemp - this->WaterOutletTemp) /
    4396            0 :                                                         (SysWaterInTemp - this->WaterOutletTemp)) -
    4397            0 :                                                        (this->PumpHeattoFluid / (CpFluid * (SysWaterInTemp - this->WaterOutletTemp)));
    4398              :                         } else {
    4399            0 :                             this->WaterInjectionRate = this->WaterMassFlowRate;
    4400              :                         }
    4401            0 :                         this->WaterRecircRate = this->WaterMassFlowRate - this->WaterInjectionRate;
    4402              : 
    4403            0 :                     } else if ((SysWaterInTemp > state.dataLowTempRadSys->LoopReqTemp) &&
    4404            0 :                                (coldNode.MassFlowRateMaxAvail >= this->WaterMassFlowRate)) {
    4405              :                         // Case 2: Adequate flow but temperature too high
    4406              :                         // Only thing to do is to reset the inlet temperature and assume that the loop will supply
    4407              :                         // the entire flow to the component (no recirculation but potentially some bypass for the
    4408              :                         // overall loop).  There is no way we can meet the control temperature so don't even try.
    4409            0 :                         this->WaterInletTemp = SysWaterInTemp + PumpTempRise;
    4410            0 :                         this->calculateLowTemperatureRadiantSystemComponents(state, LoopInNode, Iteration, LoadMet, SystemType::ConstantFlow);
    4411              : 
    4412              :                         // We now have inlet and outlet temperatures--we still need to set the flow rates
    4413            0 :                         if ((SysWaterInTemp - this->WaterOutletTemp) != 0.0) { // protect div by zero
    4414            0 :                             this->WaterInjectionRate = (this->WaterMassFlowRate * (this->WaterInletTemp - this->WaterOutletTemp) /
    4415            0 :                                                         (SysWaterInTemp - this->WaterOutletTemp)) -
    4416            0 :                                                        (this->PumpHeattoFluid / (CpFluid * (SysWaterInTemp - this->WaterOutletTemp)));
    4417              :                         } else { // no temp change present, set injection rate to full flow
    4418            0 :                             this->WaterInjectionRate = this->WaterMassFlowRate;
    4419              :                         }
    4420            0 :                         if (this->WaterInjectionRate > this->WaterMassFlowRate) this->WaterInjectionRate = this->WaterMassFlowRate;
    4421            0 :                         this->WaterRecircRate = 0.0; // by definition
    4422              : 
    4423            0 :                     } else if ((SysWaterInTemp <= state.dataLowTempRadSys->LoopReqTemp) &&
    4424            0 :                                (coldNode.MassFlowRateMaxAvail < this->WaterMassFlowRate)) {
    4425              :                         // Case 3: Adequate temperature but loop flow is less than component flow
    4426              :                         // This case might work out, but there is no guarantee that there is enough loop flow to
    4427              :                         // mix with the recirculation flow and still provide a high enough temperature.  First
    4428              :                         // step is to try the inlet temperature and flow rate as in Case 1.  If we can obtain
    4429              :                         // the proper temperature inlet to the radiant system, then we are done.  If not, we
    4430              :                         // have to repeat the solution for an unknown inlet temperature and a known recirculation
    4431              :                         // rate.
    4432              :                         // This condition might happen when state.dataLowTempRadSys->LoopReqTemp has been reset  to dewpoint for condensation control
    4433            0 :                         if (!state.dataLowTempRadSys->VarOffCond) {
    4434            0 :                             this->WaterInletTemp = RadInTemp;
    4435              :                         } else {
    4436            0 :                             this->WaterInletTemp = state.dataLowTempRadSys->LoopReqTemp;
    4437              :                         }
    4438            0 :                         this->calculateLowTemperatureRadiantSystemComponents(state, LoopInNode, Iteration, LoadMet, SystemType::ConstantFlow);
    4439              : 
    4440              :                         // Now see if we can really get that desired into temperature (RadInTemp) by solving
    4441              :                         // for the flow that is injected from the loop.  A heat balance for the mixer that relates
    4442              :                         // the important quantities is:
    4443              :                         //   Mdotradsys*Cp*Tradsysin = Mdotloop*Cp*Tloop + (Mdotradsys-Mdotloop)*Cp*Tradsysout + PumpHeat
    4444              :                         // or rearranging to get the injection flow (Mdotloop):
    4445              :                         //   Mdotloop = Mdotcomp*(Tradsysin-Tradsysout)/(Tloop-Tradsysout) - PumpHeat/(Cp*(Tloop-Tradsysout))
    4446              :                         // If Mdotloop from this equation is greater that the loop flow rate (Node%MassFlowRate),
    4447              :                         // then we cannot meet the inlet temperature and we have to "iterate" through the
    4448              :                         // alternate solution.
    4449            0 :                         if ((SysWaterInTemp - this->WaterOutletTemp) != 0.0) { // protect div by zero
    4450            0 :                             InjectFlowRate = (this->WaterMassFlowRate * (this->WaterInletTemp - this->WaterOutletTemp) /
    4451            0 :                                               (SysWaterInTemp - this->WaterOutletTemp)) -
    4452            0 :                                              (this->PumpHeattoFluid / (CpFluid * (SysWaterInTemp - this->WaterOutletTemp)));
    4453              :                         } else {
    4454            0 :                             InjectFlowRate = this->WaterMassFlowRate;
    4455              :                         }
    4456            0 :                         if (InjectFlowRate > coldNode.MassFlowRateMaxAvail) {
    4457              :                             // We didn't have enough flow from the loop to meet our inlet temperature request.
    4458              :                             // So, set the injection rate to the loop flow and calculate the recirculation flow.
    4459              :                             // Then, resimulate the radiant system using these values (it will obtain the actual
    4460              :                             // inlet temperature that results from this).
    4461            0 :                             this->WaterInjectionRate = coldNode.MassFlowRateMaxAvail;
    4462            0 :                             this->WaterRecircRate = this->WaterMassFlowRate - this->WaterInjectionRate;
    4463            0 :                             this->WaterInletTemp = SysWaterInTemp + PumpTempRise;
    4464            0 :                             Iteration = true;
    4465            0 :                             this->calculateLowTemperatureRadiantSystemComponents(state, LoopInNode, Iteration, LoadMet, SystemType::ConstantFlow);
    4466              :                         } else {
    4467            0 :                             this->WaterInjectionRate = InjectFlowRate;
    4468            0 :                             this->WaterRecircRate = this->WaterMassFlowRate - this->WaterInjectionRate;
    4469              :                         }
    4470              : 
    4471            0 :                     } else if ((SysWaterInTemp > state.dataLowTempRadSys->LoopReqTemp) && (coldNode.MassFlowRateMaxAvail < this->WaterMassFlowRate)) {
    4472              :                         // Case 4: Temperature too low and loop flow is less than component flow
    4473              :                         // Worst condition--can't meet the temperature request at all.  Only thing to do is to
    4474              :                         // set the loop flow and recirculation rate (known) and solve for the inlet temperature
    4475              :                         // using the "iteration" solution scheme from "Case 3B" above
    4476            0 :                         this->WaterInjectionRate = coldNode.MassFlowRateMaxAvail;
    4477            0 :                         this->WaterRecircRate = this->WaterMassFlowRate - this->WaterInjectionRate;
    4478            0 :                         this->WaterInletTemp = SysWaterInTemp + PumpTempRise;
    4479            0 :                         Iteration = true;
    4480            0 :                         this->calculateLowTemperatureRadiantSystemComponents(state, LoopInNode, Iteration, LoadMet, SystemType::ConstantFlow);
    4481              :                     }
    4482              : 
    4483            0 :                     ++state.dataLowTempRadSys->CFloCondIterNum;
    4484              :                 }
    4485              : 
    4486              :             } // Operating mode (heating or cooling)
    4487              : 
    4488              :             // Case when system has been shut down because of condensation issues or other limitations:
    4489            0 :             if (this->WaterMassFlowRate < DataBranchAirLoopPlant::MassFlowTolerance) {
    4490            0 :                 this->WaterMassFlowRate = 0.0;
    4491            0 :                 this->WaterInjectionRate = 0.0;
    4492            0 :                 this->WaterRecircRate = 0.0;
    4493            0 :                 this->PumpMassFlowRate = 0.0;
    4494            0 :                 this->opMode = OpMode::None;
    4495              :             }
    4496              : 
    4497              :             // There are some cases when the pump heat is actually enough to provide all the heating that the system needs.
    4498              :             // In this case, the water injection flow rate will come back as a slightly negative number.  Reset it to zero
    4499              :             // and just recirculate all the flow through the local loop.
    4500            0 :             if (this->WaterInjectionRate < 0.0) {
    4501            0 :                 this->WaterInjectionRate = 0.0;
    4502            0 :                 this->WaterRecircRate = this->WaterMassFlowRate;
    4503              :             }
    4504              : 
    4505              :             // Error check, just in case
    4506            0 :             if (this->WaterRecircRate < 0.0) {
    4507            0 :                 ShowWarningError(state, "Flow mismatch in radiant system--result will be an energy imbalance--should not get this error");
    4508            0 :                 ShowContinueErrorTimeStamp(state, format("WaterRecircRate={:.2T}, in Radiant System={},", this->WaterRecircRate, this->Name));
    4509            0 :                 this->WaterRecircRate = 0.0;
    4510            0 :                 this->WaterInjectionRate = this->WaterMassFlowRate;
    4511              :             }
    4512              : 
    4513              :         } // System running mode (yes or no)
    4514            2 :     }
    4515              : 
    4516            0 :     void ConstantFlowRadiantSystemData::calculateLowTemperatureRadiantSystemComponents(
    4517              :         EnergyPlusData &state,
    4518              :         int const MainLoopNodeIn, // Node number on main loop of the inlet node to the radiant system
    4519              :         bool const Iteration,     // FALSE for the regular solution, TRUE when we had to loop back
    4520              :         Real64 &LoadMet,          // Load met by the low temperature radiant system, in Watts
    4521              :         SystemType const typeOfRadiantSystem)
    4522              :     {
    4523              : 
    4524              :         // SUBROUTINE INFORMATION:
    4525              :         //       AUTHOR         Rick Strand
    4526              :         //       DATE WRITTEN   August 2003
    4527              :         //       MODIFIED       Sep 2011 LKL/BG - resimulate only zones needing it for Radiant systems
    4528              : 
    4529              :         // PURPOSE OF THIS SUBROUTINE:
    4530              :         // This subroutine solves the radiant system based on how much water is (and
    4531              :         // the conditions of the water) supplied to the radiant system.  The purpose
    4532              :         // of this subroutine is similar to CalcLowTempHydrRadSysComps except that
    4533              :         // it solves this for a constant flow hydronic radiant system.
    4534              : 
    4535              :         // METHODOLOGY EMPLOYED:
    4536              :         // Use heat exchanger formulas to obtain the heat source/sink for the radiant
    4537              :         // system based on the inlet conditions and flow rate of water.  Once that is
    4538              :         // determined, recalculate the surface heat balances to reflect this heat
    4539              :         // addition/subtraction.  The load met by the system is determined by the
    4540              :         // difference between the convection from all surfaces in the zone when
    4541              :         // there was no radiant system output and with a source/sink added.
    4542              : 
    4543              :         // REFERENCES:
    4544              :         // IBLAST-QTF research program, completed in January 1995 (unreleased)
    4545              :         // Strand, R.K. 1995. "Heat Source Transfer Functions and Their Application to
    4546              :         //   Low Temperature Radiant Heating Systems", Ph.D. dissertation, University
    4547              :         //   of Illinois at Urbana-Champaign, Department of Mechanical and Industrial
    4548              :         //   Engineering.
    4549              : 
    4550            0 :         auto &Zone = state.dataHeatBal->Zone;
    4551              : 
    4552              :         // Using/Aliasing
    4553              :         using PlantUtilities::SetComponentFlowRate;
    4554              : 
    4555              :         // SUBROUTINE PARAMETER DEFINITIONS:
    4556            0 :         Real64 constexpr TempCheckLimit(0.1); // Maximum allowed temperature difference between outlet temperature calculations
    4557            0 :         Real64 constexpr ZeroSystemResp(0.1); // Response below which the system response is really zero
    4558            0 :         constexpr std::string_view RoutineName("CalcLowTempCFloRadSysComps");
    4559              : 
    4560              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    4561              :         Real64 Cp;                    // Intermediate calculational variable for specific heat of water
    4562              :         Real64 DewPointTemp;          // Dew-point temperature based on the zone air conditions
    4563              :         Real64 EpsMdotCp;             // Epsilon (heat exchanger terminology) times water mass flow rate times water specific heat
    4564              :         Real64 LoopTerm;              // Intermeidate calculation variable for determining the water inlet temperature
    4565              :         Real64 Mdot;                  // Intermediate calculation variable for mass flow rate in a surface within the radiant system
    4566              :         Real64 RecircTerm;            // Intermeidate calculation variable for determining the water inlet temperature
    4567              :         Real64 SumFlowFracCkCm;       // Summation of surface flow fraction, Ck, and Cm product for each surface in the system
    4568              :         Real64 SumFlowFracOneMinusCm; // Summation of surface flow fraction times (1-Cm) for each surface in the radiant system
    4569              :         Real64 TotalRadSysPower;      // Total heat source/sink to radiant system
    4570              :         Real64 TwiCoeff;              // Intermeidate calculation variable for determining the water inlet temperature
    4571              :         Real64 WaterMassFlow;         // Water mass flow rate in the radiant system, kg/s
    4572              :         Real64 WaterOutletTempCheck;  // Radiant system water outlet temperature (calculated from mixing all outlet streams together)
    4573              :         Real64 WaterTempIn;           // Temperature of the water entering the radiant system, in C
    4574              :         int ZoneNum;                  // number of zone being served
    4575              :         Real64 ZoneMult;              // Zone multiplier for this system
    4576              : 
    4577              :         ConstantFlowRadDesignData ConstantFlowDesignDataObject =                   // I repeat myself
    4578            0 :             state.dataLowTempRadSys->CflowRadiantSysDesign(this->DesignObjectPtr); // Contains the data for variable flow hydronic systems
    4579            0 :         auto &Surface = state.dataSurface->Surface;
    4580              : 
    4581              :         Real64 Ca; // Coefficients to relate the inlet water temperature to the heat source
    4582              :         Real64 Cb;
    4583              :         Real64 Cc;
    4584              :         Real64 Cd;
    4585              :         Real64 Ce;
    4586              :         Real64 Cf;
    4587              :         Real64 Cg;
    4588              :         Real64 Ch;
    4589              :         Real64 Ci;
    4590              :         Real64 Cj;
    4591              :         Real64 Ck;
    4592              :         Real64 Cl;
    4593              :         // For more info on Ca through Cl, see comments below
    4594              : 
    4595              :         // First, apply heat exchanger logic to find the heat source/sink to the system.
    4596              :         // This involves finding out the heat transfer characteristics of the hydronic
    4597              :         // loop and then applying the equations derived on pp. 113-118 of the dissertation.
    4598            0 :         if (state.dataLowTempRadSys->FirstTimeFlag) {
    4599            0 :             state.dataLowTempRadSys->Ckj.allocate(state.dataLowTempRadSys->MaxCloNumOfSurfaces);
    4600            0 :             state.dataLowTempRadSys->Cmj.allocate(state.dataLowTempRadSys->MaxCloNumOfSurfaces);
    4601            0 :             state.dataLowTempRadSys->WaterTempOut.allocate(state.dataLowTempRadSys->MaxCloNumOfSurfaces);
    4602            0 :             state.dataLowTempRadSys->FirstTimeFlag = false;
    4603              :         }
    4604              : 
    4605            0 :         state.dataLowTempRadSys->Ckj = 0.0;
    4606            0 :         state.dataLowTempRadSys->Cmj = 0.0;
    4607            0 :         state.dataLowTempRadSys->WaterTempOut = this->WaterInletTemp;
    4608              : 
    4609            0 :         ZoneNum = this->ZonePtr;
    4610            0 :         ZoneMult = double(Zone(ZoneNum).Multiplier * Zone(ZoneNum).ListMultiplier);
    4611            0 :         WaterMassFlow = this->WaterMassFlowRate / ZoneMult;
    4612            0 :         WaterTempIn = this->WaterInletTemp;
    4613              : 
    4614            0 :         if (WaterMassFlow <= 0.0) {
    4615              :             // No flow or below minimum allowed so there is no heat source/sink
    4616              :             // This is possible with a mismatch between system and plant operation
    4617              :             // or a slight mismatch between zone and system controls.  This is not
    4618              :             // necessarily a "problem" so this exception is necessary in the code.
    4619            0 :             for (int RadSurfNum = 1; RadSurfNum <= this->NumOfSurfaces; ++RadSurfNum) {
    4620            0 :                 int SurfNum = this->SurfacePtr(RadSurfNum);
    4621            0 :                 state.dataHeatBalFanSys->QRadSysSource(SurfNum) = 0.0;
    4622            0 :                 if (Surface(SurfNum).ExtBoundCond > 0 && Surface(SurfNum).ExtBoundCond != SurfNum)
    4623            0 :                     state.dataHeatBalFanSys->QRadSysSource(Surface(SurfNum).ExtBoundCond) = 0.0; // Also zero the other side of an interzone
    4624              :             }
    4625              : 
    4626            0 :             this->WaterOutletTemp = this->WaterInletTemp;
    4627              : 
    4628              :         } else {
    4629              : 
    4630            0 :             for (int RadSurfNum = 1; RadSurfNum <= this->NumOfSurfaces; ++RadSurfNum) {
    4631            0 :                 int SurfNum = this->SurfacePtr(RadSurfNum);
    4632              :                 // Determine the heat exchanger "effectiveness" term
    4633              : 
    4634            0 :                 EpsMdotCp = calculateHXEffectivenessTerm(state,
    4635              :                                                          SurfNum,
    4636              :                                                          WaterTempIn,
    4637              :                                                          WaterMassFlow,
    4638            0 :                                                          this->SurfaceFrac(RadSurfNum),
    4639            0 :                                                          this->NumCircuits(RadSurfNum),
    4640              :                                                          this->DesignObjectPtr,
    4641              :                                                          typeOfRadiantSystem);
    4642              : 
    4643              :                 // Obtain the heat balance coefficients and calculate the intermediate coefficients
    4644              :                 // linking the inlet water temperature to the heat source/sink to the radiant system.
    4645              :                 // The coefficients are based on the following development...
    4646              :                 // The heat balance equations at the outside and inside surfaces are of the form:
    4647              :                 //   Tinside  = Ca + Cb*Toutside + Cc*q"
    4648              :                 //   Toutside = Cd + Ce*Tinside  + Cf*q"
    4649              :                 //   Tsource  = Cg + Ch*q"       + Ci*Tinside + Cj*Toutside
    4650              :                 // where:
    4651              :                 //   Tinside is the temperature at the inside surface
    4652              :                 //   Toutside is the temperature at the outside surface
    4653              :                 //   Tsource is the temperature within the radiant system at the location of the source/sink
    4654              :                 //   Ca is all of the other terms in the inside heat balance (solar, LW exchange, conduction history terms, etc.)
    4655              :                 //   Cb is the current cross CTF term
    4656              :                 //   Cc is the QTF inside term for the current heat source/sink
    4657              :                 //   Cd is all of the other terms in the outside heat balance (solar, LW exchange, conduction history terms, etc.)
    4658              :                 //   Ce is the current cross CTF term (should be equal to Cb)
    4659              :                 //   Cf is the QTF outside term for the current heat source/sink
    4660              :                 //   Cg is the summation of all temperature and source history terms at the source/sink location
    4661              :                 //   Ch is the QTF term at the source/sink location for the current heat source/sink
    4662              :                 //   Ci is the CTF inside term for the current inside surface temperature
    4663              :                 //   Cj is the CTF outside term for the current outside surface temperature
    4664              :                 // Note that it is necessary to not use "slow conduction" assumptions because the
    4665              :                 // source/sink has an impact on BOTH the inside and outside surface heat balances.
    4666              :                 // Hence the more general formulation.
    4667              :                 // The first two T equations above can be solved to remove the other surface temperature.
    4668              :                 // This results in the following equations:
    4669              :                 //   Tinside  = Ca + Cb*(Cd + Ce*Tinside + Cf*q") + Cc*q"   or...
    4670              :                 //   Tinside  = (Ca + Cb*Cd + (Cc+Cb*Cf)*q") / (1 - Ce*Cb)
    4671              :                 //   Toutside = Cd + Ce*(Ca + Cb*Toutside + Cc*q") + Cf*q"  or...
    4672              :                 //   Toutside = (Cd + Ce*Ca + (Cf+Ce*Cc)*q") / (1 - Ce*Cb)
    4673              :                 // Substituting the new equations for Tinside and Toutside as a function of C and q"
    4674              :                 // into the equation for Tsource...
    4675              :                 //   Tsource  = Cg + Ch*q" + Ci*((Ca + Cb*Cd + (Cc+Cb*Cf)*q") / (1 - Ce*Cb)) &
    4676              :                 //                         + Cj*((Cd + Ce*Ca + (Cf+Ce*Cc)*q") / (1 - Ce*Cb))
    4677              :                 // Or rearranging this to get Tsource as a function of q", we get...
    4678              :                 //   Tsource  =  Cg + ((Ci*(Ca + Cb*Cd) + Cj*(Cd + Ce*Ca))/(1-Ce*Cb)) &
    4679              :                 //             +(Ch + ((Ci*(Cc + Cb*Cf) + Cj*(Cf + Ce*Cc))/(1-Ce*Cb)))*q"
    4680              :                 // Or in a slightly simpler form...
    4681              :                 //   Tsource  = Ck + Cl*q"
    4682              :                 // where:
    4683              :                 //   Ck = Cg + ((Ci*(Ca + Cb*Cd) + Cj*(Cd + Ce*Ca))/(1-Ce*Cb))
    4684              :                 //   Cl = Ch + ((Ci*(Cc + Cb*Cf) + Cj*(Cf + Ce*Cc))/(1-Ce*Cb))
    4685              :                 // Note also that from heat exchanger "algebra", we have:
    4686              :                 //   q = epsilon*qmax    and    qmax = Mdot*Cp*(Twaterin-Tsource)
    4687              :                 // So...
    4688              :                 //   q" = q/Area = (epsilon*Mdot*Cp/Area)*(Twaterin-Tsource)
    4689              :                 // Or rearranging this equation:
    4690              :                 //   Tsource = -(q"*A/(epsilon*Mdot*Cp)) + Twaterin
    4691              :                 // Setting this equation equal to the other equation for Tsource a couple lines up
    4692              :                 // and rearranging to solve for q"...
    4693              :                 //   q" = (Twaterin - Ck) / (Cl + (A/(epsilon*Mdot*Cp))
    4694              :                 // or
    4695              :                 //   q  = (Twaterin - Ck) / ((Cl/A) + (1/epsilon*Mdot*Cp))
    4696              :                 // or
    4697              :                 //   q  = epsilon*Mdot*Cp*(Twaterin - Ck) / (1+(epsilon*Mdot*Cp*Cl/A))
    4698              :                 // which is the desired result, that is the heat source or sink to the radiant
    4699              :                 // system as a function of the water inlet temperature (flow rate is also in there
    4700              :                 // as well as all of the heat balance terms "hidden" in Ck and Cl).
    4701              : 
    4702            0 :                 int ConstrNum = Surface(SurfNum).Construction;
    4703            0 :                 auto const &thisConstruct = state.dataConstruction->Construct(ConstrNum);
    4704              : 
    4705            0 :                 Ca = state.dataHeatBalFanSys->RadSysTiHBConstCoef(SurfNum);
    4706            0 :                 Cb = state.dataHeatBalFanSys->RadSysTiHBToutCoef(SurfNum);
    4707            0 :                 Cc = state.dataHeatBalFanSys->RadSysTiHBQsrcCoef(SurfNum);
    4708              : 
    4709            0 :                 Cd = state.dataHeatBalFanSys->RadSysToHBConstCoef(SurfNum);
    4710            0 :                 Ce = state.dataHeatBalFanSys->RadSysToHBTinCoef(SurfNum);
    4711            0 :                 Cf = state.dataHeatBalFanSys->RadSysToHBQsrcCoef(SurfNum);
    4712              : 
    4713            0 :                 Cg = state.dataHeatBalFanSys->CTFTsrcConstPart(SurfNum);
    4714            0 :                 Ch = thisConstruct.CTFTSourceQ[0];
    4715            0 :                 Ci = thisConstruct.CTFTSourceIn[0];
    4716            0 :                 Cj = thisConstruct.CTFTSourceOut[0];
    4717              : 
    4718            0 :                 Ck = Cg + ((Ci * (Ca + Cb * Cd) + Cj * (Cd + Ce * Ca)) / (1.0 - Ce * Cb));
    4719            0 :                 Cl = Ch + ((Ci * (Cc + Cb * Cf) + Cj * (Cf + Ce * Cc)) / (1.0 - Ce * Cb));
    4720              : 
    4721            0 :                 Mdot = WaterMassFlow * this->SurfaceFrac(RadSurfNum);
    4722            0 :                 Cp = this->water->getSpecificHeat(state, WaterTempIn, RoutineName);
    4723              : 
    4724            0 :                 if (!Iteration) {
    4725              : 
    4726            0 :                     if (Surface(SurfNum).HeatTransferAlgorithm == DataSurfaces::HeatTransferModel::CTF)
    4727            0 :                         state.dataHeatBalFanSys->QRadSysSource(SurfNum) =
    4728            0 :                             EpsMdotCp * (WaterTempIn - Ck) / (1.0 + (EpsMdotCp * Cl / Surface(SurfNum).Area));
    4729              : 
    4730            0 :                     if (Surface(SurfNum).HeatTransferAlgorithm == DataSurfaces::HeatTransferModel::CondFD)
    4731            0 :                         state.dataHeatBalFanSys->QRadSysSource(SurfNum) =
    4732            0 :                             EpsMdotCp * (WaterTempIn - state.dataHeatBalFanSys->TCondFDSourceNode(SurfNum));
    4733              : 
    4734            0 :                     if (Surface(SurfNum).ExtBoundCond > 0 && Surface(SurfNum).ExtBoundCond != SurfNum)
    4735            0 :                         state.dataHeatBalFanSys->QRadSysSource(Surface(SurfNum).ExtBoundCond) =
    4736            0 :                             state.dataHeatBalFanSys->QRadSysSource(SurfNum); // Also set the other side of an interzone
    4737            0 :                     state.dataLowTempRadSys->WaterTempOut(RadSurfNum) = WaterTempIn - (state.dataHeatBalFanSys->QRadSysSource(SurfNum) / (Mdot * Cp));
    4738              :                 } else { // (Iteration)
    4739              :                     // In this case, we did not know the inlet temperature directly and have
    4740              :                     // to figure it out as part of the solution.  Thus, we have to do a little
    4741              :                     // more algebra.
    4742              :                     // The last equation in the previous block was:
    4743              :                     //   q = epsilon*Mdot*Cp*(Twaterin - Ck) / (1+(epsilon*Mdot*Cp*Cl/A))
    4744              :                     // which combines with:
    4745              :                     //   q = Mdot*Cp*(Twaterin - Twaterout,j)
    4746              :                     // so that:
    4747              :                     //   (Twaterin - Twaterout.j) = epsilon*(Twaterin - Ck) / (1+(epsilon*Mdot*Cp*Cl/A))
    4748              :                     // Let:
    4749              :                     //   Cm = epsilonj / (1+(epsilonj*Mdot,j*Cp*Cl,j/A))
    4750              :                     // for each surface in the radiant system.  This results in:
    4751              :                     //   (Twaterin - Twaterout,j) = Cm,j*(Twaterin - Ck,j)
    4752              :                     // Or:
    4753              :                     //   Twaterout,j = (1 - Cm,j)*Twaterin + Cm,j*Ck,j
    4754              :                     // This holds for each surface that is part of the radiant system (j).  To get the
    4755              :                     // overall outlet temperature, we have to do a mixing calculation after all of the
    4756              :                     // surfaces have been simulated:
    4757              :                     //   Twaterout = SUM(Fractionj*Twaterout,j)
    4758              :                     // We also have to solve an energy balance at the mixing valve and add in pump heat.
    4759              :                     // The energy balance at the mixing valve relates the loop inlet temperature (Tloopin)
    4760              :                     // and the overall outlet temperature (Twaterout):
    4761              :                     //   Tpumpin = (Mdotloop/Mdotradsys)*Tloopin + (Mdotrecirc/Mdotradsys)*Twaterout
    4762              :                     // This can then be related to the inlet water temperature to the radiant system
    4763              :                     // after pump heat has been taken into account:
    4764              :                     //   Twaterin = (Mdotloop/Mdotradsys)*Tloopin + (Mdotrecirc/Mdotradsys)*Twaterout + PumpHeat/(Mdotradsys*Cp)
    4765              :                     // Pluggin in the definition of Twaterout (sum equation above) and then the definition
    4766              :                     // of each individual Twaterout,j equation (which is solely a function of Twaterin
    4767              :                     // and coefficients), we can obtain an equation for Twaterin that consists of all
    4768              :                     // known quantities.  This requires us to calculate Ck,j and Cm,j for all the radiant
    4769              :                     // surfaces in the system first and then coming up with a calculation for Twaterin.
    4770              :                     // After than, individual Twaterout,j can be calculated along with QRadSysSource.
    4771            0 :                     state.dataLowTempRadSys->Ckj(RadSurfNum) = Ck;
    4772            0 :                     state.dataLowTempRadSys->Cmj(RadSurfNum) = (EpsMdotCp / (Mdot * Cp)) / (1.0 + (EpsMdotCp * Cl / Surface(SurfNum).Area));
    4773              : 
    4774            0 :                     if (RadSurfNum == this->NumOfSurfaces) { // Last one so we can now do the other calculations
    4775              :                         // Equation for Twaterin is:
    4776              :                         //   Twaterin = (LoopTerm + RecircTerm)/(TwiCoeff)
    4777              :                         // where:
    4778              :                         //   LoopTerm   = (Mdotloop/Mdotradsys)*Tloopin + PumpHeat/(Mdotradsys*Cp)
    4779              :                         //   RecircTerm = (Mdotrecirc/Mdotradsys)*SUM(FlowFracj*Ck,j*Cm,j)
    4780              :                         //   TwiCoeff   = 1 - (Mdotrecirc/Mdotradsys)*SUM(FlowFracj*(1 - Cm,j))
    4781            0 :                         SumFlowFracCkCm = 0.0;
    4782            0 :                         SumFlowFracOneMinusCm = 0.0;
    4783            0 :                         for (int RadSurfNum2 = 1; RadSurfNum2 <= this->NumOfSurfaces; ++RadSurfNum2) {
    4784            0 :                             SumFlowFracCkCm += (this->SurfaceFrac(RadSurfNum2) * state.dataLowTempRadSys->Ckj(RadSurfNum) *
    4785            0 :                                                 state.dataLowTempRadSys->Cmj(RadSurfNum2));
    4786            0 :                             SumFlowFracOneMinusCm += (this->SurfaceFrac(RadSurfNum2) * (1.0 - state.dataLowTempRadSys->Cmj(RadSurfNum2)));
    4787              :                         }
    4788              : 
    4789            0 :                         LoopTerm = (this->WaterInjectionRate / this->WaterMassFlowRate) * state.dataLoopNodes->Node(MainLoopNodeIn).Temp +
    4790            0 :                                    (this->PumpHeattoFluid / (this->WaterMassFlowRate * Cp));
    4791              : 
    4792            0 :                         RecircTerm = (this->WaterRecircRate / this->WaterMassFlowRate) * SumFlowFracCkCm;
    4793              : 
    4794            0 :                         TwiCoeff = 1.0 - (this->WaterRecircRate / this->WaterMassFlowRate) * SumFlowFracOneMinusCm;
    4795              : 
    4796            0 :                         WaterTempIn = (LoopTerm + RecircTerm) / (TwiCoeff);
    4797              : 
    4798            0 :                         this->WaterInletTemp = WaterTempIn;
    4799              : 
    4800            0 :                         for (int RadSurfNum2 = 1; RadSurfNum2 <= this->NumOfSurfaces; ++RadSurfNum2) {
    4801            0 :                             state.dataLowTempRadSys->WaterTempOut(RadSurfNum2) =
    4802            0 :                                 WaterTempIn * (1.0 - state.dataLowTempRadSys->Cmj(RadSurfNum2)) +
    4803            0 :                                 (state.dataLowTempRadSys->Ckj(RadSurfNum2) * state.dataLowTempRadSys->Cmj(RadSurfNum2));
    4804            0 :                             Mdot = WaterMassFlow * this->SurfaceFrac(RadSurfNum2);
    4805            0 :                             int SurfNum2 = this->SurfacePtr(RadSurfNum2);
    4806            0 :                             state.dataHeatBalFanSys->QRadSysSource(SurfNum2) =
    4807            0 :                                 Mdot * Cp * (WaterTempIn - state.dataLowTempRadSys->WaterTempOut(RadSurfNum2));
    4808            0 :                             if (Surface(SurfNum2).ExtBoundCond > 0 && Surface(SurfNum2).ExtBoundCond != SurfNum2)
    4809            0 :                                 state.dataHeatBalFanSys->QRadSysSource(Surface(SurfNum2).ExtBoundCond) =
    4810            0 :                                     state.dataHeatBalFanSys->QRadSysSource(SurfNum2); // Also set the other side of an interzone
    4811              :                         }
    4812              :                     }
    4813              :                 }
    4814              :             }
    4815              : 
    4816            0 :             for (int RadSurfNum = 1; RadSurfNum <= this->NumOfSurfaces; ++RadSurfNum) {
    4817            0 :                 int SurfNum = this->SurfacePtr(RadSurfNum);
    4818              :                 // "Temperature Comparison" Cut-off:
    4819              :                 // Check to see whether or not the system should really be running.  If
    4820              :                 // QRadSysSource is negative when we are in heating mode or QRadSysSource
    4821              :                 // is positive when we are in cooling mode, then the radiant system will
    4822              :                 // be doing the opposite of its intention.  In this case, the flow rate
    4823              :                 // is set to zero to avoid heating in cooling mode or cooling in heating
    4824              :                 // mode.
    4825            0 :                 if (((this->opMode == OpMode::Heat) && (state.dataHeatBalFanSys->QRadSysSource(SurfNum) <= 0.0)) ||
    4826            0 :                     ((this->opMode == OpMode::Cool) && (state.dataHeatBalFanSys->QRadSysSource(SurfNum) >= 0.0))) {
    4827            0 :                     WaterMassFlow = 0.0;
    4828            0 :                     if (this->opMode == OpMode::Heat) {
    4829            0 :                         SetComponentFlowRate(state, WaterMassFlow, this->HotWaterInNode, this->HotWaterOutNode, this->HWPlantLoc);
    4830            0 :                     } else if (this->opMode == OpMode::Cool) {
    4831            0 :                         SetComponentFlowRate(state, WaterMassFlow, this->ColdWaterInNode, this->ColdWaterOutNode, this->CWPlantLoc);
    4832              :                     }
    4833            0 :                     this->WaterMassFlowRate = WaterMassFlow;
    4834            0 :                     this->opMode = OpMode::None;
    4835            0 :                     for (int RadSurfNum2 = 1; RadSurfNum2 <= this->NumOfSurfaces; ++RadSurfNum2) {
    4836            0 :                         int SurfNum2 = this->SurfacePtr(RadSurfNum2);
    4837            0 :                         state.dataHeatBalFanSys->QRadSysSource(SurfNum2) = 0.0;
    4838            0 :                         if (Surface(SurfNum2).ExtBoundCond > 0 && Surface(SurfNum2).ExtBoundCond != SurfNum2)
    4839            0 :                             state.dataHeatBalFanSys->QRadSysSource(Surface(SurfNum2).ExtBoundCond) = 0.0; // Also zero the other side of an interzone
    4840              :                     }
    4841            0 :                     break; // outer do loop
    4842              :                 }
    4843              :             }
    4844              :             // Condensation Cut-off:
    4845              :             // Check to see whether there are any surface temperatures within the radiant system that have
    4846              :             // dropped below the dew-point temperature.  If so, we need to shut off this radiant system.
    4847              :             // A safety parameter is added (hardwired parameter) to avoid getting too close to condensation
    4848              :             // conditions.
    4849            0 :             this->CondCausedShutDown = false;
    4850            0 :             DewPointTemp =
    4851            0 :                 PsyTdpFnWPb(state, state.dataZoneTempPredictorCorrector->zoneHeatBalance(this->ZonePtr).airHumRat, state.dataEnvrn->OutBaroPress);
    4852              : 
    4853            0 :             if ((this->opMode == OpMode::Cool) && (ConstantFlowDesignDataObject.condCtrlType == CondCtrlType::SimpleOff)) {
    4854              : 
    4855            0 :                 for (int RadSurfNum2 = 1; RadSurfNum2 <= this->NumOfSurfaces; ++RadSurfNum2) {
    4856            0 :                     if (state.dataHeatBalSurf->SurfInsideTempHist(1)(this->SurfacePtr(RadSurfNum2)) <
    4857            0 :                         (DewPointTemp + ConstantFlowDesignDataObject.CondDewPtDeltaT)) {
    4858              :                         // Condensation warning--must shut off radiant system
    4859            0 :                         this->CondCausedShutDown = true;
    4860            0 :                         WaterMassFlow = 0.0;
    4861            0 :                         this->opMode = OpMode::None;
    4862            0 :                         SetComponentFlowRate(state, WaterMassFlow, this->ColdWaterInNode, this->ColdWaterOutNode, this->CWPlantLoc);
    4863            0 :                         this->WaterMassFlowRate = WaterMassFlow;
    4864            0 :                         for (int RadSurfNum3 = 1; RadSurfNum3 <= this->NumOfSurfaces; ++RadSurfNum3) {
    4865            0 :                             int SurfNum2 = this->SurfacePtr(RadSurfNum3);
    4866            0 :                             state.dataHeatBalFanSys->QRadSysSource(SurfNum2) = 0.0;
    4867            0 :                             if (Surface(SurfNum2).ExtBoundCond > 0 && Surface(SurfNum2).ExtBoundCond != SurfNum2)
    4868            0 :                                 state.dataHeatBalFanSys->QRadSysSource(Surface(SurfNum2).ExtBoundCond) =
    4869              :                                     0.0; // Also zero the other side of an interzone
    4870              :                         }
    4871              :                         // Produce a warning message so that user knows the system was shut-off due to potential for condensation
    4872            0 :                         if (!state.dataGlobal->WarmupFlag) {
    4873            0 :                             if (this->CondErrIndex == 0) { // allow errors up to number of radiant systems
    4874            0 :                                 ShowWarningMessage(state, format("{} [{}]", cConstantFlowSystem, this->Name));
    4875            0 :                                 ShowContinueError(state,
    4876            0 :                                                   format("Surface [{}] temperature below dew-point temperature--potential for condensation exists",
    4877            0 :                                                          Surface(this->SurfacePtr(RadSurfNum2)).Name));
    4878            0 :                                 ShowContinueError(state, "Flow to the radiant system will be shut-off to avoid condensation");
    4879            0 :                                 ShowContinueError(state,
    4880            0 :                                                   format("Predicted radiant system surface temperature = {:.2R}",
    4881            0 :                                                          state.dataHeatBalSurf->SurfInsideTempHist(1)(this->SurfacePtr(RadSurfNum2))));
    4882            0 :                                 ShowContinueError(state,
    4883            0 :                                                   format("Zone dew-point temperature + safety delta T= {:.2R}",
    4884            0 :                                                          DewPointTemp + ConstantFlowDesignDataObject.CondDewPtDeltaT));
    4885            0 :                                 ShowContinueErrorTimeStamp(state, "");
    4886            0 :                                 ShowContinueError(state,
    4887            0 :                                                   format("Note that a {:.4R} C safety was chosen in the input for the shut-off criteria",
    4888              :                                                          ConstantFlowDesignDataObject.CondDewPtDeltaT));
    4889            0 :                                 ShowContinueError(state, "Note also that this affects all surfaces that are part of this radiant system");
    4890              :                             }
    4891            0 :                             ShowRecurringWarningErrorAtEnd(
    4892              :                                 state,
    4893            0 :                                 format("{} [{}] condensation shut-off occurrence continues.", cConstantFlowSystem, this->Name),
    4894            0 :                                 this->CondErrIndex,
    4895              :                                 DewPointTemp,
    4896              :                                 DewPointTemp,
    4897              :                                 _,
    4898              :                                 "C",
    4899              :                                 "C");
    4900              :                         }
    4901            0 :                         break; // outer do loop
    4902              :                     }
    4903              :                 }
    4904              : 
    4905            0 :             } else if ((this->opMode == OpMode::Cool) && (ConstantFlowDesignDataObject.condCtrlType == CondCtrlType::None)) {
    4906              : 
    4907            0 :                 for (int RadSurfNum2 = 1; RadSurfNum2 <= this->NumOfSurfaces; ++RadSurfNum2) {
    4908            0 :                     if (state.dataHeatBalSurf->SurfInsideTempHist(1)(this->SurfacePtr(RadSurfNum2)) < DewPointTemp) {
    4909              :                         // Condensation occurring but user does not want to shut radiant system off ever
    4910            0 :                         this->CondCausedShutDown = true;
    4911              :                     }
    4912              :                 }
    4913              : 
    4914            0 :             } else if ((this->opMode == OpMode::Cool) && (ConstantFlowDesignDataObject.condCtrlType == CondCtrlType::VariedOff)) {
    4915              : 
    4916            0 :                 for (int RadSurfNum2 = 1; RadSurfNum2 <= this->NumOfSurfaces; ++RadSurfNum2) {
    4917            0 :                     if (state.dataHeatBalSurf->SurfInsideTempHist(1)(this->SurfacePtr(RadSurfNum2)) <
    4918            0 :                         (DewPointTemp + ConstantFlowDesignDataObject.CondDewPtDeltaT)) {
    4919            0 :                         state.dataLowTempRadSys->VarOffCond = true;
    4920            0 :                         if (state.dataLowTempRadSys->CFloCondIterNum >= 2) {
    4921              :                             // We have already iterated once so now we must shut off radiant system
    4922            0 :                             this->CondCausedShutDown = true;
    4923            0 :                             WaterMassFlow = 0.0;
    4924            0 :                             this->opMode = OpMode::None;
    4925            0 :                             SetComponentFlowRate(state, WaterMassFlow, this->ColdWaterInNode, this->ColdWaterOutNode, this->CWPlantLoc);
    4926            0 :                             this->WaterMassFlowRate = WaterMassFlow;
    4927            0 :                             for (int RadSurfNum3 = 1; RadSurfNum3 <= this->NumOfSurfaces; ++RadSurfNum3) {
    4928            0 :                                 int SurfNum2 = this->SurfacePtr(RadSurfNum3);
    4929            0 :                                 state.dataHeatBalFanSys->QRadSysSource(SurfNum2) = 0.0;
    4930            0 :                                 if (Surface(SurfNum2).ExtBoundCond > 0 && Surface(SurfNum2).ExtBoundCond != SurfNum2)
    4931            0 :                                     state.dataHeatBalFanSys->QRadSysSource(Surface(SurfNum2).ExtBoundCond) =
    4932              :                                         0.0; // Also zero the other side of an interzone
    4933              :                             }
    4934              :                             // Produce a warning message so that user knows the system was shut-off due to potential for condensation
    4935            0 :                             if (!state.dataGlobal->WarmupFlag) {
    4936            0 :                                 if (this->CondErrIndex == 0) { // allow errors up to number of radiant systems
    4937            0 :                                     ShowWarningMessage(state, format("{} [{}]", cConstantFlowSystem, this->Name));
    4938            0 :                                     ShowContinueError(
    4939              :                                         state,
    4940            0 :                                         format("Surface [{}] temperature below dew-point temperature--potential for condensation exists",
    4941            0 :                                                Surface(this->SurfacePtr(RadSurfNum2)).Name));
    4942            0 :                                     ShowContinueError(state, "Flow to the radiant system will be shut-off to avoid condensation");
    4943            0 :                                     ShowContinueError(state,
    4944            0 :                                                       format("Predicted radiant system surface temperature = {:.2R}",
    4945            0 :                                                              state.dataHeatBalSurf->SurfInsideTempHist(1)(this->SurfacePtr(RadSurfNum2))));
    4946            0 :                                     ShowContinueError(state,
    4947            0 :                                                       format("Zone dew-point temperature + safety delta T= {:.2R}",
    4948            0 :                                                              DewPointTemp + ConstantFlowDesignDataObject.CondDewPtDeltaT));
    4949            0 :                                     ShowContinueErrorTimeStamp(state, "");
    4950            0 :                                     ShowContinueError(state,
    4951            0 :                                                       format("Note that a {:.4R} C safety was chosen in the input for the shut-off criteria",
    4952              :                                                              ConstantFlowDesignDataObject.CondDewPtDeltaT));
    4953            0 :                                     ShowContinueError(state, "Note also that this affects all surfaces that are part of this radiant system");
    4954              :                                 }
    4955            0 :                                 ShowRecurringWarningErrorAtEnd(
    4956              :                                     state,
    4957            0 :                                     format("{} [{}] condensation shut-off occurrence continues.", cConstantFlowSystem, this->Name),
    4958            0 :                                     this->CondErrIndex,
    4959              :                                     DewPointTemp,
    4960              :                                     DewPointTemp,
    4961              :                                     _,
    4962              :                                     "C",
    4963              :                                     "C");
    4964              :                             }
    4965            0 :                             break; // outer do loop
    4966              :                         } else {   // (First iteration--reset loop required temperature and try again to avoid condensation)
    4967            0 :                             state.dataLowTempRadSys->LoopReqTemp = DewPointTemp + ConstantFlowDesignDataObject.CondDewPtDeltaT;
    4968              :                         }
    4969              :                     }
    4970              :                 }
    4971              :             }
    4972              : 
    4973              :             // Determine radiant system outlet temperature (two ways to calculate--use as a check)
    4974            0 :             WaterOutletTempCheck = 0.0;
    4975            0 :             TotalRadSysPower = 0.0;
    4976            0 :             for (int RadSurfNum = 1; RadSurfNum <= this->NumOfSurfaces; ++RadSurfNum) {
    4977            0 :                 int SurfNum = this->SurfacePtr(RadSurfNum);
    4978            0 :                 TotalRadSysPower += state.dataHeatBalFanSys->QRadSysSource(SurfNum);
    4979            0 :                 WaterOutletTempCheck += (this->SurfaceFrac(RadSurfNum) * state.dataLowTempRadSys->WaterTempOut(RadSurfNum));
    4980              :             }
    4981            0 :             TotalRadSysPower *= ZoneMult;
    4982              : 
    4983            0 :             if (this->WaterMassFlowRate > 0.0) {
    4984            0 :                 Cp = this->water->getSpecificHeat(state, WaterTempIn, RoutineName);
    4985            0 :                 this->WaterOutletTemp = this->WaterInletTemp - (TotalRadSysPower / (this->WaterMassFlowRate * Cp));
    4986            0 :                 if ((std::abs(this->WaterOutletTemp - WaterOutletTempCheck) > TempCheckLimit) && (std::abs(TotalRadSysPower) > ZeroSystemResp)) {
    4987              :                     // If the total system power is zero, that means we have shut down and the temperatures won't match because of that
    4988            0 :                     ShowWarningError(state, "Radiant system water outlet temperature calculation mismatch--this should not happen");
    4989              :                 }
    4990              :             } else {
    4991            0 :                 this->WaterOutletTemp = this->WaterInletTemp;
    4992              :             }
    4993              :         }
    4994              : 
    4995              :         // Now that we have the source/sink term(s), we must redo the heat balances to obtain
    4996              :         // the new SumHATsurf value for the zone.  Note that the difference between the new
    4997              :         // SumHATsurf and the value originally calculated by the heat balance with a zero
    4998              :         // source for all radiant systems in the zone is the load met by the system (approximately).
    4999            0 :         HeatBalanceSurfaceManager::CalcHeatBalanceOutsideSurf(state, ZoneNum);
    5000            0 :         HeatBalanceSurfaceManager::CalcHeatBalanceInsideSurf(state, ZoneNum);
    5001              : 
    5002            0 :         LoadMet = state.dataHeatBal->Zone(this->ZonePtr).sumHATsurf(state) - this->ZeroLTRSourceSumHATsurf;
    5003            0 :     }
    5004              :     // TODO Write unit tests for baseboard
    5005            4 :     void ConstantFlowRadiantSystemData::calculateRunningMeanAverageTemperature(EnergyPlusData &state, int RadSysNum)
    5006              :     {
    5007              :         // This routine grabs the current weather data since it is currently available at this point in the simulation.  Note, however,
    5008              :         // that the formula that calculates the running mean average (dry-bulb) temperature uses the values from "yesterday".  So, today's
    5009              :         // values are calculated and then shifted at the beginning of the next day to the tomorrow variables.  It is these tomorrow variables
    5010              :         // that are then used in the formula.  So, that is why some of the assignments are done in the order that they are in below.
    5011              : 
    5012            4 :         ConstantFlowRadDesignData constantFlowDesignDataObject{state.dataLowTempRadSys->CflowRadiantSysDesign(
    5013            4 :             state.dataLowTempRadSys->CFloRadSys(RadSysNum).DesignObjectPtr)}; // Contains the data for constant flow hydronic systems
    5014              : 
    5015            4 :         if (state.dataGlobal->DayOfSim == 1 && state.dataGlobal->WarmupFlag) {
    5016              :             // there is no "history" here--assume everything that came before was the same (this applies to design days also--weather is always the
    5017              :             // same
    5018            1 :             this->todayAverageOutdoorDryBulbTemperature = this->calculateCurrentDailyAverageODB(state);
    5019            1 :             this->yesterdayAverageOutdoorDryBulbTemperature = this->todayAverageOutdoorDryBulbTemperature;
    5020            1 :             this->todayRunningMeanOutdoorDryBulbTemperature = this->todayAverageOutdoorDryBulbTemperature;
    5021            1 :             this->yesterdayRunningMeanOutdoorDryBulbTemperature = this->todayAverageOutdoorDryBulbTemperature;
    5022            3 :         } else if (!state.dataGlobal->WarmupFlag && state.dataGlobal->NumOfDayInEnvrn > 1) {
    5023              :             // This is an environment with more than one day (non-design day) so...
    5024              :             // First update yesterday's information using what was previously calculated for "today"
    5025            1 :             this->yesterdayAverageOutdoorDryBulbTemperature = this->todayAverageOutdoorDryBulbTemperature;
    5026            1 :             this->yesterdayRunningMeanOutdoorDryBulbTemperature = this->todayRunningMeanOutdoorDryBulbTemperature;
    5027              :             // Now update the running mean and average outdoor air temperatures
    5028            1 :             this->todayRunningMeanOutdoorDryBulbTemperature =
    5029            1 :                 (1.0 - constantFlowDesignDataObject.runningMeanOutdoorAirTemperatureWeightingFactor) *
    5030            1 :                     this->yesterdayAverageOutdoorDryBulbTemperature +
    5031            1 :                 constantFlowDesignDataObject.runningMeanOutdoorAirTemperatureWeightingFactor * this->yesterdayRunningMeanOutdoorDryBulbTemperature;
    5032            1 :             this->todayAverageOutdoorDryBulbTemperature = this->calculateCurrentDailyAverageODB(state);
    5033              :         }
    5034            4 :     }
    5035              : 
    5036            2 :     Real64 ConstantFlowRadiantSystemData::calculateCurrentDailyAverageODB(EnergyPlusData &state)
    5037              :     {
    5038            2 :         Real64 sum = 0.0;
    5039           50 :         for (int hourNumber = 1; hourNumber <= Constant::iHoursInDay; ++hourNumber) {
    5040           96 :             for (int timeStepNumber = 1; timeStepNumber <= state.dataGlobal->TimeStepsInHour; ++timeStepNumber) {
    5041           48 :                 sum += state.dataWeather->wvarsHrTsToday(timeStepNumber, hourNumber).OutDryBulbTemp;
    5042              :             }
    5043              :         }
    5044            2 :         return sum / (Constant::rHoursInDay * state.dataGlobal->TimeStepsInHour);
    5045              :     }
    5046              : 
    5047            0 :     void ElectricRadiantSystemData::calculateLowTemperatureRadiantSystem(EnergyPlusData &state,
    5048              :                                                                          Real64 &LoadMet) // load met by the radiant system, in Watts
    5049              :     {
    5050              : 
    5051              :         // SUBROUTINE INFORMATION:
    5052              :         //       AUTHOR         Rick Strand
    5053              :         //       DATE WRITTEN   November 2000
    5054              :         //       MODIFIED       Sep 2011 LKL/BG - resimulate only zones needing it for Radiant systems
    5055              : 
    5056              :         // PURPOSE OF THIS SUBROUTINE:
    5057              :         // This subroutine does all of the stuff that is necessary to simulate
    5058              :         // a low temperature electric radiant heating system.  Calls are made to
    5059              :         // appropriate subroutines either in this module or outside of it.
    5060              : 
    5061              :         // METHODOLOGY EMPLOYED:
    5062              :         // Follows the methods used by many other pieces of zone equipment except
    5063              :         // that we are controlling the electrical input to the building element's
    5064              :         // resistance heating wires.  Note that cooling is not allowed for such
    5065              :         // a system.
    5066              : 
    5067              :         // REFERENCES:
    5068              :         // Other EnergyPlus modules
    5069              :         // IBLAST-QTF research program, completed in January 1995 (unreleased)
    5070              :         // Strand, R.K. 1995. "Heat Source Transfer Functions and Their Application to
    5071              :         //   Low Temperature Radiant Heating Systems", Ph.D. dissertation, University
    5072              :         //   of Illinois at Urbana-Champaign, Department of Mechanical and Industrial
    5073              :         //   Engineering.
    5074              :         // Seem, J.E. 1986. "Heat Transfer in Buildings", Ph.D. dissertation, University
    5075              :         //   of Wisconsin-Madison.
    5076              : 
    5077              :         // Using/Aliasing
    5078              :         using DataHeatBalance::ZoneData;
    5079              :         using HVAC::SmallLoad;
    5080              : 
    5081              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    5082              :         Real64 ControlTemp; // Temperature of the parameter that is controlling the radiant system
    5083              :         Real64 HeatFrac;    // fraction of maximum electrical heat input to radiant system [dimensionless]
    5084              :         Real64 OffTemp;     // Temperature above which the radiant system should be completely off [C]
    5085              :         int RadSurfNum;     // number of surface that is the radiant system
    5086              :         int SurfNum;        // intermediate variable for surface number in Surface derived type
    5087              :         int ZoneNum;        // number of zone being served
    5088              : 
    5089              :         // initialize local variables
    5090            0 :         ZoneNum = this->ZonePtr;
    5091            0 :         HeatFrac = 0.0;
    5092            0 :         auto &Surface = state.dataSurface->Surface;
    5093              : 
    5094            0 :         if (this->availSched->getCurrentVal() <= 0.0) {
    5095              : 
    5096              :             // Unit is off; set the heat source terms to zero
    5097            0 :             for (RadSurfNum = 1; RadSurfNum <= this->NumOfSurfaces; ++RadSurfNum) {
    5098            0 :                 SurfNum = this->SurfacePtr(RadSurfNum);
    5099            0 :                 state.dataHeatBalFanSys->QRadSysSource(SurfNum) = 0.0;
    5100            0 :                 if (Surface(SurfNum).ExtBoundCond > 0 && Surface(SurfNum).ExtBoundCond != SurfNum)
    5101            0 :                     state.dataHeatBalFanSys->QRadSysSource(Surface(SurfNum).ExtBoundCond) = 0.0; // Also zero the other side of an interzone
    5102              :             }
    5103              : 
    5104              :         } else { // Unit might be on-->this section is intended to determine whether the controls say
    5105              :             // that the unit should be on or not
    5106              : 
    5107              :             // Determine the current setpoint temperature and the temperature at which the unit should be completely off
    5108            0 :             OffTemp = this->setOffTemperatureLowTemperatureRadiantSystem(state, this->setptSched, this->ThrottlRange, this->setpointType);
    5109              : 
    5110              :             // Determine the control temperature--what the setpoint/offtemp is being compared to for unit operation
    5111              : 
    5112            0 :             ControlTemp = this->setRadiantSystemControlTemperature(state, controlType);
    5113              : 
    5114            0 :             if (ControlTemp < OffTemp) { // HEATING MODE
    5115              : 
    5116            0 :                 this->opMode = OpMode::Heat;
    5117              : 
    5118            0 :                 HeatFrac = this->calculateOperationalFraction(OffTemp, ControlTemp, this->ThrottlRange);
    5119              : 
    5120              :                 // Set the heat source for the low temperature electric radiant system
    5121            0 :                 for (RadSurfNum = 1; RadSurfNum <= this->NumOfSurfaces; ++RadSurfNum) {
    5122            0 :                     SurfNum = this->SurfacePtr(RadSurfNum);
    5123            0 :                     state.dataHeatBalFanSys->QRadSysSource(SurfNum) = HeatFrac * this->MaxElecPower * this->SurfaceFrac(RadSurfNum);
    5124            0 :                     if (Surface(SurfNum).ExtBoundCond > 0 && Surface(SurfNum).ExtBoundCond != SurfNum)
    5125            0 :                         state.dataHeatBalFanSys->QRadSysSource(Surface(SurfNum).ExtBoundCond) =
    5126            0 :                             state.dataHeatBalFanSys->QRadSysSource(SurfNum); // Also set the other side of an interzone
    5127              :                 }
    5128              : 
    5129              :                 // Now "simulate" the system by recalculating the heat balances
    5130            0 :                 HeatBalanceSurfaceManager::CalcHeatBalanceOutsideSurf(state, ZoneNum);
    5131            0 :                 HeatBalanceSurfaceManager::CalcHeatBalanceInsideSurf(state, ZoneNum);
    5132              : 
    5133            0 :                 LoadMet = state.dataHeatBal->Zone(ZoneNum).sumHATsurf(state) - this->ZeroLTRSourceSumHATsurf;
    5134              : 
    5135              :             } else { //  OFF or COOLING MODE (not allowed for an electric low temperature radiant system), turn it off
    5136              : 
    5137            0 :                 for (RadSurfNum = 1; RadSurfNum <= this->NumOfSurfaces; ++RadSurfNum) {
    5138            0 :                     SurfNum = this->SurfacePtr(RadSurfNum);
    5139            0 :                     state.dataHeatBalFanSys->QRadSysSource(SurfNum) = 0.0;
    5140            0 :                     if (Surface(SurfNum).ExtBoundCond > 0 && Surface(SurfNum).ExtBoundCond != SurfNum)
    5141            0 :                         state.dataHeatBalFanSys->QRadSysSource(Surface(SurfNum).ExtBoundCond) = 0.0; // Also zero the other side of an interzone
    5142              :                 }
    5143              :             }
    5144              :         }
    5145            0 :     }
    5146              : 
    5147            0 :     void RadiantSystemBaseData::updateLowTemperatureRadiantSystemSurfaces(EnergyPlusData &state)
    5148              :     {
    5149              : 
    5150              :         // The purpose of this routine is to update the average heat source/sink for a particular system over the various system time
    5151              :         // steps that make up the zone time step.  For hydronic systems, this routine must also set the outlet water conditions.
    5152              :         // For the source/sink average update, if the system time step elapsed is still what it used to be, then either we are still
    5153              :         // iterating orwe had to go back and shorten the time step.  As a result, we have to subtract out the previous value that we
    5154              :         // added.  If the system time step elapsed is different, then we just need to add the new values to the running average.
    5155              : 
    5156            0 :         Real64 TimeStepSys = state.dataHVACGlobal->TimeStepSys;
    5157            0 :         Real64 SysTimeElapsed = state.dataHVACGlobal->SysTimeElapsed;
    5158            0 :         Real64 TimeStepZone = state.dataGlobal->TimeStepZone;
    5159              : 
    5160            0 :         for (int radSurfNum = 1; radSurfNum <= this->NumOfSurfaces; ++radSurfNum) {
    5161              : 
    5162            0 :             int surfNum = this->SurfacePtr(radSurfNum);
    5163              : 
    5164            0 :             if (this->LastSysTimeElapsed == SysTimeElapsed) {
    5165              :                 // Still iterating or reducing system time step, so subtract old values which were
    5166              :                 // not valid
    5167            0 :                 this->QRadSysSrcAvg(radSurfNum) -= this->LastQRadSysSrc(radSurfNum) * this->LastTimeStepSys / TimeStepZone;
    5168              :             }
    5169              : 
    5170              :             // Update the running average and the "last" values with the current values of the appropriate variables
    5171            0 :             this->QRadSysSrcAvg(radSurfNum) += state.dataHeatBalFanSys->QRadSysSource(surfNum) * TimeStepSys / TimeStepZone;
    5172            0 :             this->LastQRadSysSrc(radSurfNum) = state.dataHeatBalFanSys->QRadSysSource(surfNum);
    5173              :         }
    5174            0 :         this->LastSysTimeElapsed = SysTimeElapsed;
    5175            0 :         this->LastTimeStepSys = TimeStepSys;
    5176            0 :     }
    5177              : 
    5178            0 :     void VariableFlowRadiantSystemData::updateLowTemperatureRadiantSystem(EnergyPlusData &state)
    5179              :     {
    5180              : 
    5181              :         // Using/Aliasing
    5182              :         using PlantUtilities::SafeCopyPlantNode;
    5183              :         using PlantUtilities::SetComponentFlowRate;
    5184              : 
    5185              :         // SUBROUTINE PARAMETER DEFINITIONS:
    5186            0 :         constexpr std::string_view RoutineName("UpdateVariableFlowSystem");
    5187              : 
    5188              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    5189              :         Real64 cpWater;       // Specific heat of water
    5190              :         int waterInletNode;   // Node number for the water side inlet of the radiant system
    5191              :         Real64 waterMassFlow; // Flow rate of water in the radiant system
    5192              :         int waterOutletNode;  // Node number for the water side outlet of the radiant system
    5193              : 
    5194            0 :         auto &Zone = state.dataHeatBal->Zone;
    5195            0 :         auto &Node = state.dataLoopNodes->Node;
    5196              : 
    5197              :         // For a hydronic system, calculate the water side outlet conditions and set the
    5198              :         // appropriate conditions on the correct HVAC node.
    5199              : 
    5200              :         // First sum up all of the heat sources/sinks associated with this system
    5201            0 :         Real64 TotalHeatSource(0.0); // Total heat source or sink for a particular radiant system (sum of all surface source/sinks)
    5202            0 :         for (int radSurfNum = 1; radSurfNum <= this->NumOfSurfaces; ++radSurfNum) {
    5203            0 :             TotalHeatSource += state.dataHeatBalFanSys->QRadSysSource(this->SurfacePtr(radSurfNum));
    5204              :         }
    5205            0 :         TotalHeatSource *= double(Zone(this->ZonePtr).Multiplier * Zone(this->ZonePtr).ListMultiplier);
    5206              : 
    5207              :         // Update the heating side of things
    5208            0 :         if (this->HeatingSystem) {
    5209              : 
    5210            0 :             waterInletNode = this->HotWaterInNode;
    5211            0 :             waterOutletNode = this->HotWaterOutNode;
    5212            0 :             waterMassFlow = Node(waterInletNode).MassFlowRate;
    5213              : 
    5214            0 :             cpWater = state.dataPlnt->PlantLoop(this->HWPlantLoc.loopNum).glycol->getSpecificHeat(state, Node(waterInletNode).Temp, RoutineName);
    5215              : 
    5216            0 :             if (this->opMode == OpMode::Heat) {
    5217            0 :                 if ((cpWater > 0.0) && (waterMassFlow > 0.0)) {
    5218            0 :                     SafeCopyPlantNode(state, waterInletNode, waterOutletNode);
    5219            0 :                     Node(waterOutletNode).Temp = Node(waterInletNode).Temp - TotalHeatSource / waterMassFlow / cpWater;
    5220              :                 } else {
    5221            0 :                     SafeCopyPlantNode(state, waterInletNode, waterOutletNode);
    5222              :                 }
    5223              : 
    5224              :             } else { // OpMode::Cool or not on
    5225            0 :                 SafeCopyPlantNode(state, waterInletNode, waterOutletNode);
    5226              :             }
    5227              : 
    5228            0 :             this->checkForOutOfRangeTemperatureResult(state, Node(waterOutletNode).Temp, Node(waterInletNode).Temp);
    5229              :         }
    5230              : 
    5231            0 :         if (this->CoolingSystem) {
    5232              : 
    5233            0 :             waterInletNode = this->ColdWaterInNode;
    5234            0 :             waterOutletNode = this->ColdWaterOutNode;
    5235            0 :             waterMassFlow = Node(waterInletNode).MassFlowRate;
    5236              : 
    5237            0 :             cpWater = state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).glycol->getSpecificHeat(state, Node(waterInletNode).Temp, RoutineName);
    5238              : 
    5239            0 :             if (this->opMode == OpMode::Cool) {
    5240            0 :                 if ((cpWater > 0.0) && (waterMassFlow > 0.0)) {
    5241            0 :                     SafeCopyPlantNode(state, waterInletNode, waterOutletNode);
    5242            0 :                     Node(waterOutletNode).Temp = Node(waterInletNode).Temp - TotalHeatSource / waterMassFlow / cpWater;
    5243              :                 } else {
    5244            0 :                     SafeCopyPlantNode(state, waterInletNode, waterOutletNode);
    5245              :                 }
    5246              : 
    5247              :             } else { // OpMode::Heat or not on
    5248            0 :                 SafeCopyPlantNode(state, waterInletNode, waterOutletNode);
    5249              :             }
    5250              : 
    5251            0 :             this->checkForOutOfRangeTemperatureResult(state, Node(waterOutletNode).Temp, Node(waterInletNode).Temp);
    5252              :         }
    5253            0 :     }
    5254              : 
    5255            0 :     void ConstantFlowRadiantSystemData::updateLowTemperatureRadiantSystem(EnergyPlusData &state)
    5256              :     {
    5257              : 
    5258              :         // Using/Aliasing
    5259              :         using PlantUtilities::SafeCopyPlantNode;
    5260              :         using PlantUtilities::SetComponentFlowRate;
    5261              : 
    5262              :         Real64 bypassMassFlow; // Local bypass for a constant flow radiant system (could have recirculation and/or bypass)
    5263              :         int waterInletNode;    // Node number for the water side inlet of the radiant system
    5264              :         int waterOutletNode;   // Node number for the water side outlet of the radiant system
    5265              : 
    5266              :         // For a constant flow system, calculate the water side outlet conditions
    5267              :         // and set the appropriate conditions on the correct HVAC node.  This may
    5268              :         // require mixing if the main system does not provide all of the flow that
    5269              :         // the local radiant system circulates.
    5270              : 
    5271              :         // Update the heating side of things
    5272            0 :         if (this->HeatingSystem) {
    5273              : 
    5274            0 :             waterInletNode = this->HotWaterInNode;
    5275            0 :             waterOutletNode = this->HotWaterOutNode;
    5276            0 :             SafeCopyPlantNode(state, waterInletNode, waterOutletNode);
    5277              : 
    5278            0 :             if (this->opMode == OpMode::Heat) {
    5279              : 
    5280              :                 // Leave the inlet and outlet flow alone (if high enough) and perform a bypass if more flow than needed
    5281            0 :                 if (state.dataLoopNodes->Node(waterInletNode).MassFlowRate <= this->WaterInjectionRate) {
    5282              :                     // Note that the water injection rate has already been restricted to the maximum available flow
    5283            0 :                     state.dataLoopNodes->Node(waterOutletNode).Temp = this->WaterOutletTemp;
    5284              :                 } else {
    5285              :                     // Loop is providing more flow than needed so perform a local bypass and
    5286              :                     // mix the flows to obtain the proper outlet temperature.  In this case,
    5287              :                     // the mass flow rates on the loop are left alone and the outlet temperature
    5288              :                     // is calculated from a simple steady-steady, steady-flow energy balance.
    5289            0 :                     bypassMassFlow = state.dataLoopNodes->Node(waterInletNode).MassFlowRate - this->WaterInjectionRate;
    5290            0 :                     state.dataLoopNodes->Node(waterOutletNode).Temp =
    5291            0 :                         ((bypassMassFlow * state.dataLoopNodes->Node(waterInletNode).Temp) + (this->WaterInjectionRate * this->WaterOutletTemp)) /
    5292            0 :                         (state.dataLoopNodes->Node(waterOutletNode).MassFlowRate);
    5293              :                 }
    5294              :             }
    5295            0 :             this->checkForOutOfRangeTemperatureResult(
    5296            0 :                 state, state.dataLoopNodes->Node(waterOutletNode).Temp, state.dataLoopNodes->Node(waterInletNode).Temp);
    5297              :         }
    5298              : 
    5299            0 :         if (this->CoolingSystem) {
    5300              : 
    5301            0 :             waterInletNode = this->ColdWaterInNode;
    5302            0 :             waterOutletNode = this->ColdWaterOutNode;
    5303            0 :             SafeCopyPlantNode(state, waterInletNode, waterOutletNode);
    5304              : 
    5305            0 :             if (this->opMode == OpMode::Cool) {
    5306              : 
    5307            0 :                 if (state.dataLoopNodes->Node(waterInletNode).MassFlowRate <= this->WaterInjectionRate) {
    5308              :                     // Note that the water injection rate has already been restricted to the maximum available flow
    5309              : 
    5310            0 :                     state.dataLoopNodes->Node(waterOutletNode).Temp = this->WaterOutletTemp;
    5311              :                 } else {
    5312              :                     // Loop is providing more flow than needed so perform a local bypass and
    5313              :                     // mix the flows to obtain the proper outlet temperature.  In this case,
    5314              :                     // the mass flow rates on the loop are left alone and the outlet temperature
    5315              :                     // is calculated from a simple steady-steady, steady-flow energy balance.
    5316            0 :                     bypassMassFlow = state.dataLoopNodes->Node(waterInletNode).MassFlowRate - this->WaterInjectionRate;
    5317            0 :                     state.dataLoopNodes->Node(waterOutletNode).Temp =
    5318            0 :                         ((bypassMassFlow * state.dataLoopNodes->Node(waterInletNode).Temp) + (this->WaterInjectionRate * this->WaterOutletTemp)) /
    5319            0 :                         (state.dataLoopNodes->Node(waterOutletNode).MassFlowRate);
    5320              :                 }
    5321              : 
    5322            0 :                 this->checkForOutOfRangeTemperatureResult(
    5323            0 :                     state, state.dataLoopNodes->Node(waterOutletNode).Temp, state.dataLoopNodes->Node(waterInletNode).Temp);
    5324              :             }
    5325              :         }
    5326            0 :     }
    5327              : 
    5328            0 :     void ElectricRadiantSystemData::updateLowTemperatureRadiantSystem([[maybe_unused]] EnergyPlusData &state)
    5329              :     { // Dummy routine: no updates are needed for electric radiant systems
    5330            0 :     }
    5331              : 
    5332            0 :     void HydronicSystemBaseData::checkForOutOfRangeTemperatureResult(EnergyPlusData &state, Real64 const outletTemp, Real64 const inletTemp)
    5333              :     {
    5334              : 
    5335              :         // SUBROUTINE INFORMATION:
    5336              :         //       AUTHOR         B. Griffith
    5337              :         //       DATE WRITTEN   March 2013
    5338              : 
    5339              :         // PURPOSE OF THIS SUBROUTINE:
    5340              :         // check for crazy, out of range temperature results for fluid leaving radiant system
    5341              : 
    5342              :         // Using/Aliasing
    5343              : 
    5344            0 :         Real64 constexpr upperRangeLimit(500.0);  // high error trigger limit for when model is not working
    5345            0 :         Real64 constexpr lowerRangeLimit(-300.0); // Low error trigger limit for when model is not working
    5346              : 
    5347            0 :         if (outletTemp < lowerRangeLimit) {
    5348            0 :             state.dataLowTempRadSys->warnTooLow = true;
    5349              :         }
    5350              : 
    5351            0 :         if (outletTemp > upperRangeLimit) {
    5352            0 :             state.dataLowTempRadSys->warnTooHigh = true;
    5353              :         }
    5354              : 
    5355            0 :         if (state.dataLowTempRadSys->warnTooLow || state.dataLowTempRadSys->warnTooHigh) {
    5356            0 :             if (state.dataLowTempRadSys->warnTooLow) {
    5357            0 :                 if (this->OutRangeLoErrorCount == 0) {
    5358            0 :                     ShowSevereMessage(state, "UpdateLowTempRadiantSystem: model result for fluid outlet temperature is not physical.");
    5359            0 :                     ShowContinueError(state, format("Occurs for radiant system name = {}", this->Name));
    5360            0 :                     ShowContinueError(state, format("Calculated radiant system outlet temperature = {:.3R} [C]", outletTemp));
    5361            0 :                     ShowContinueError(state, format("Radiant system inlet temperature = {:.3R} [C]", inletTemp));
    5362            0 :                     ShowContinueError(
    5363              :                         state, "A possible cause is that the materials used in the internal source construction are not compatible with the model.");
    5364              :                 }
    5365            0 :                 ShowRecurringSevereErrorAtEnd(
    5366              :                     state,
    5367            0 :                     "UpdateLowTempRadiantSystem: Detected low out of range outlet temperature result for radiant system name =" + this->Name,
    5368            0 :                     this->OutRangeLoErrorCount,
    5369              :                     outletTemp,
    5370              :                     outletTemp);
    5371              :             }
    5372              : 
    5373            0 :             if (state.dataLowTempRadSys->warnTooHigh) {
    5374            0 :                 if (this->OutRangeHiErrorCount == 0) {
    5375            0 :                     ShowSevereMessage(state, "UpdateLowTempRadiantSystem: model result for fluid outlet temperature is not physical.");
    5376            0 :                     ShowContinueError(state, format("Occurs for radiant system name = {}", this->Name));
    5377            0 :                     ShowContinueError(state, format("Calculated radiant system outlet temperature = {:.3R} [C]", outletTemp));
    5378            0 :                     ShowContinueError(state, format("Radiant system inlet temperature = {:.3R} [C]", inletTemp));
    5379            0 :                     ShowContinueError(
    5380              :                         state, "A possible cause is that the materials used in the internal source construction are not compatible with the model.");
    5381              :                 }
    5382            0 :                 ShowRecurringSevereErrorAtEnd(
    5383              :                     state,
    5384            0 :                     "UpdateLowTempRadiantSystem: Detected high out of range outlet temperature result radiant system name =" + this->Name,
    5385            0 :                     this->OutRangeHiErrorCount,
    5386              :                     outletTemp,
    5387              :                     outletTemp);
    5388              :             }
    5389              :         }
    5390            0 :     }
    5391              : 
    5392           26 :     Real64 RadiantSystemBaseData::setRadiantSystemControlTemperature(EnergyPlusData &state, CtrlType TempControlType)
    5393              :     {
    5394           26 :         auto &thisZoneHB = state.dataZoneTempPredictorCorrector->zoneHeatBalance(this->ZonePtr);
    5395           26 :         switch (TempControlType) {
    5396            7 :         case CtrlType::MAT:
    5397            7 :             return thisZoneHB.MAT;
    5398            3 :         case CtrlType::MRT:
    5399            3 :             return thisZoneHB.MRT;
    5400            3 :         case CtrlType::Operative:
    5401            3 :             return 0.5 * (thisZoneHB.MAT + thisZoneHB.MRT);
    5402            3 :         case CtrlType::ODB:
    5403            3 :             return state.dataHeatBal->Zone(this->ZonePtr).OutDryBulbTemp;
    5404            3 :         case CtrlType::OWB:
    5405            3 :             return state.dataHeatBal->Zone(this->ZonePtr).OutWetBulbTemp;
    5406            3 :         case CtrlType::SurfFaceTemp:
    5407            3 :             return state.dataHeatBalSurf->SurfTempIn(this->SurfacePtr(1)); // Grabs the inside face temperature of the first surface in the list
    5408            3 :         case CtrlType::SurfIntTemp:
    5409            3 :             return state.dataHeatBalSurf->SurfTempUserLoc(
    5410            3 :                 this->SurfacePtr(1)); // Grabs the temperature inside the slab at the location specified by the user
    5411            1 :         case CtrlType::RunningMeanODB:
    5412            1 :             return this->todayRunningMeanOutdoorDryBulbTemperature;
    5413            0 :         default:
    5414            0 :             ShowSevereError(state, format("Illegal control type in low temperature radiant system or it's design object: {}", this->Name));
    5415            0 :             ShowFatalError(state, "Preceding condition causes termination.");
    5416            0 :             return 0.0; // hush the compiler
    5417              :         }
    5418              :     }
    5419              : 
    5420              :     Real64
    5421            8 :     RadiantSystemBaseData::calculateOperationalFraction(Real64 const offTemperature, Real64 const controlTemperature, Real64 const throttlingRange)
    5422              :     {
    5423            8 :         Real64 temperatureDifference = std::abs(offTemperature - controlTemperature);
    5424            8 :         if (temperatureDifference <= 0.0) {
    5425            1 :             return 0.0; // No temperature difference--turn things off (set to zero); technically shouldn't happen
    5426            7 :         } else if (throttlingRange < 0.001) {
    5427            2 :             return 1.0; // Throttling range is essentially zero and there is a temperature difference--turn it full on
    5428              :         } else {
    5429              :             // Temperature difference is non-zero and less than the throttling range--calculate the operation fraction, but limit to a maximum of 1.0
    5430            5 :             return min(temperatureDifference / throttlingRange, 1.0);
    5431              :         }
    5432              :     }
    5433              : 
    5434           10 :     Real64 RadiantSystemBaseData::setOffTemperatureLowTemperatureRadiantSystem(EnergyPlusData &state,
    5435              :                                                                                Sched::Schedule const *sched,
    5436              :                                                                                const Real64 throttlingRange,
    5437              :                                                                                SetpointType setpointType)
    5438              :     {
    5439           10 :         Real64 scheduleValue = sched->getCurrentVal();
    5440           10 :         switch (setpointType) {
    5441            7 :         case SetpointType::HalfFlowPower:
    5442            7 :             return scheduleValue + 0.5 * throttlingRange;
    5443            3 :         case SetpointType::ZeroFlowPower:
    5444            3 :             return scheduleValue;
    5445            0 :         default:
    5446            0 :             ShowSevereError(state, format("Illegal setpoint type in low temperature radiant system: {}", this->Name));
    5447            0 :             ShowFatalError(state, "Preceding condition causes termination.");
    5448            0 :             return scheduleValue + 0.5 * throttlingRange; // hush the compiler
    5449              :         }
    5450              :     }
    5451              : 
    5452              :     Real64
    5453            4 :     HydronicSystemBaseData::calculateHXEffectivenessTerm(EnergyPlusData &state,
    5454              :                                                          int const SurfNum,          // Surface number for this particular part of the radiant system
    5455              :                                                          Real64 const Temperature,   // Temperature of water entering the radiant system, in C
    5456              :                                                          Real64 const WaterMassFlow, // Mass flow rate of water in the radiant system, in kg/s
    5457              :                                                          Real64 const FlowFraction,  // Mass flow rate fraction for this surface in the radiant system
    5458              :                                                          Real64 const NumCircs,      // Number of fluid circuits in this surface
    5459              :                                                          int const DesignObjPtr,     // Design Object Pointer
    5460              :                                                          SystemType const typeOfRadiantSystem)
    5461              :     {
    5462              : 
    5463              :         // SUBROUTINE INFORMATION:
    5464              :         //       AUTHOR         Rick Strand
    5465              :         //       DATE WRITTEN   December 2000
    5466              : 
    5467              :         // PURPOSE OF THIS SUBROUTINE:
    5468              :         // This subroutine calculates the radiant system "heat exchanger"
    5469              :         // effectiveness term.  This is equal to the mass flow rate of water
    5470              :         // times the specific heat of water times the effectiveness of
    5471              :         // the heat exchanger (radiant system "coil").
    5472              : 
    5473              :         // METHODOLOGY EMPLOYED:
    5474              :         // Assumes that the only real heat transfer term that we have to
    5475              :         // deal with is the convection from the water to the tube.  The
    5476              :         // other assumptions are that the tube inside surface temperature
    5477              :         // is equal to the "source location temperature" and that it is
    5478              :         // a CONSTANT throughout the radiant system.  This is to make
    5479              :         // the problem more tractable and to fit with other system assumptions
    5480              :         // that were made elsewhere in the radiant system model.
    5481              : 
    5482              :         // REFERENCES:
    5483              :         // Property data for water shown below as parameters taken from
    5484              :         //   Incropera and DeWitt, Introduction to Heat Transfer, Table A.6.
    5485              :         // Heat exchanger information also from Incropera and DeWitt.
    5486              :         // Code based loosely on code from IBLAST program (research version)
    5487              : 
    5488              :         // Return value
    5489              :         Real64 calculateHXEffectivenessTerm;
    5490              : 
    5491              :         // SUBROUTINE PARAMETER DEFINITIONS:
    5492            4 :         Real64 constexpr MaxLaminarRe(2300.0); // Maximum Reynolds number for laminar flow
    5493            4 :         int constexpr NumOfPropDivisions(13);
    5494            4 :         Real64 constexpr MaxExpPower(50.0); // Maximum power after which EXP argument would be zero for DP variables
    5495              :         Array1D<Real64> Temps(NumOfPropDivisions,
    5496            4 :                               {1.85, 6.85, 11.85, 16.85, 21.85, 26.85, 31.85, 36.85, 41.85, 46.85, 51.85, 56.85, 61.85}); // Temperature, in C
    5497              :         Array1D<Real64> Mu(NumOfPropDivisions,
    5498              :                            {0.001652,
    5499              :                             0.001422,
    5500              :                             0.001225,
    5501              :                             0.00108,
    5502              :                             0.000959,
    5503              :                             0.000855,
    5504              :                             0.000769,
    5505              :                             0.000695,
    5506              :                             0.000631,
    5507              :                             0.000577,
    5508              :                             0.000528,
    5509              :                             0.000489,
    5510            4 :                             0.000453}); // Viscosity, in Ns/m2
    5511              :         Array1D<Real64> Conductivity(
    5512            4 :             NumOfPropDivisions, {0.574, 0.582, 0.590, 0.598, 0.606, 0.613, 0.620, 0.628, 0.634, 0.640, 0.645, 0.650, 0.656}); // Conductivity, in W/mK
    5513              :         Array1D<Real64> Pr(NumOfPropDivisions,
    5514            4 :                            {12.22, 10.26, 8.81, 7.56, 6.62, 5.83, 5.20, 4.62, 4.16, 3.77, 3.42, 3.15, 2.88}); // Prandtl number (dimensionless)
    5515            4 :         constexpr std::string_view RoutineName("calculateHXEffectivenessTerm");
    5516              : 
    5517              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    5518              :         int Index;
    5519              :         Real64 InterpFrac;
    5520              :         Real64 NuD;
    5521              :         Real64 ReD;
    5522              :         Real64 NTU;
    5523            4 :         Real64 CpWater(0.0);
    5524              :         Real64 Kactual;
    5525              :         Real64 MUactual;
    5526              :         Real64 PRactual;
    5527              :         Real64 Eff; // HX effectiveness
    5528              : 
    5529            4 :         FluidToSlabHeatTransferType FluidToSlabHeatTransfer(FluidToSlabHeatTransferType::ConvectionOnly);
    5530            4 :         Real64 TubeDiameterInner(0.0); // inside tube diameter for embedded tubing (meters)
    5531            4 :         Real64 TubeDiameterOuter(0.0); // outside tube diameter for embedded tubing (meters)
    5532              : 
    5533            4 :         if (typeOfRadiantSystem == SystemType::Hydronic) {
    5534              :             VarFlowRadDesignData variableFlowDesignDataObject{
    5535            2 :                 state.dataLowTempRadSys->HydronicRadiantSysDesign(DesignObjPtr)}; // Contains the data for variable flow hydronic systems
    5536            2 :             FluidToSlabHeatTransfer = variableFlowDesignDataObject.FluidToSlabHeatTransfer;
    5537            2 :             TubeDiameterInner = variableFlowDesignDataObject.TubeDiameterInner;
    5538            2 :             TubeDiameterOuter = variableFlowDesignDataObject.TubeDiameterOuter;
    5539            2 :         }
    5540            4 :         if (typeOfRadiantSystem == SystemType::ConstantFlow) {
    5541              :             ConstantFlowRadDesignData constantFlowDesignDataObject{
    5542            2 :                 state.dataLowTempRadSys->CflowRadiantSysDesign(DesignObjPtr)}; // Contains the data for constant flow hydronic systems
    5543            2 :             FluidToSlabHeatTransfer = constantFlowDesignDataObject.FluidToSlabHeatTransfer;
    5544            2 :             TubeDiameterInner = constantFlowDesignDataObject.TubeDiameterInner;
    5545            2 :             TubeDiameterOuter = constantFlowDesignDataObject.TubeDiameterOuter;
    5546            2 :         }
    5547              : 
    5548              :         // First find out where we are in the range of temperatures
    5549            4 :         Index = 1;
    5550           12 :         while (Index <= NumOfPropDivisions) {
    5551           12 :             if (Temperature < Temps(Index)) break; // DO loop
    5552            8 :             ++Index;
    5553              :         }
    5554              : 
    5555              :         // Initialize thermal properties of water
    5556            4 :         if (Index == 1) {
    5557            0 :             MUactual = Mu(Index);
    5558            0 :             Kactual = Conductivity(Index);
    5559            0 :             PRactual = Pr(Index);
    5560            4 :         } else if (Index > NumOfPropDivisions) {
    5561            0 :             Index = NumOfPropDivisions;
    5562            0 :             MUactual = Mu(Index);
    5563            0 :             Kactual = Conductivity(Index);
    5564            0 :             PRactual = Pr(Index);
    5565              :         } else {
    5566            4 :             InterpFrac = (Temperature - Temps(Index - 1)) / (Temps(Index) - Temps(Index - 1));
    5567            4 :             MUactual = Mu(Index - 1) + InterpFrac * (Mu(Index) - Mu(Index - 1));
    5568            4 :             Kactual = Conductivity(Index - 1) + InterpFrac * (Conductivity(Index) - Conductivity(Index - 1));
    5569            4 :             PRactual = Pr(Index - 1) + InterpFrac * (Pr(Index) - Pr(Index - 1));
    5570              :         }
    5571              :         // arguments are glycol name, temperature, and concentration
    5572            4 :         switch (this->opMode) {
    5573            2 :         case OpMode::Heat: {
    5574            2 :             CpWater = state.dataPlnt->PlantLoop(this->HWPlantLoc.loopNum).glycol->getSpecificHeat(state, Temperature, RoutineName);
    5575            2 :         } break;
    5576            2 :         case OpMode::Cool: {
    5577            2 :             CpWater = state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum).glycol->getSpecificHeat(state, Temperature, RoutineName);
    5578            2 :         } break;
    5579            0 :         default: {
    5580            0 :             assert(false);
    5581              :         } break;
    5582              :         }
    5583              : 
    5584              :         // Calculate NTU based on the heat transfer model
    5585              : 
    5586            4 :         if (FluidToSlabHeatTransfer == FluidToSlabHeatTransferType::ISOStandard) {
    5587              : 
    5588            0 :             Real64 U = this->calculateUFromISOStandard(state, SurfNum, WaterMassFlow * FlowFraction, typeOfRadiantSystem, DesignObjPtr);
    5589              : 
    5590              :             // Calculate the NTU parameter
    5591              :             // NTU = UA/[(Mdot*Cp)min]
    5592              :             // where: U = h (convection coefficient) and h = (k)(Nu)/D
    5593              :             //        A = Constant::Pi()*D*TubeLength
    5594            0 :             NTU = U * Constant::Pi * TubeDiameterOuter * this->TubeLength / (WaterMassFlow * CpWater); // FlowFraction cancels out here
    5595              :         } else { // (this->FluidToSlabHeatTransfer == FluidToSlabHeatTransferTypes::ConvectionOnly)
    5596              : 
    5597              :             // Calculate the Reynold's number from RE=(4*Mdot)/(Pi*Mu*Diameter)
    5598            4 :             ReD = 4.0 * WaterMassFlow * FlowFraction / (Constant::Pi * MUactual * TubeDiameterInner * NumCircs);
    5599              : 
    5600              :             // Calculate the Nusselt number based on what flow regime one is in
    5601            4 :             if (ReD >= MaxLaminarRe) { // Turbulent flow --> use Colburn equation
    5602              : 
    5603            0 :                 NuD = 0.023 * std::pow(ReD, 0.8) * std::pow(PRactual, 1.0 / 3.0);
    5604              : 
    5605              :             } else { // Laminar flow --> use constant surface temperature relation
    5606              : 
    5607            4 :                 NuD = 3.66;
    5608              :             }
    5609              : 
    5610              :             // Calculate the NTU parameter
    5611              :             // NTU = UA/[(Mdot*Cp)min]
    5612              :             // where: U = h (convection coefficient) and h = (k)(Nu)/D
    5613              :             //        A = Pi*D*TubeLength
    5614            4 :             NTU = Constant::Pi * Kactual * NuD * this->TubeLength / (WaterMassFlow * CpWater); // FlowFraction cancels out here
    5615              :         }
    5616              : 
    5617              :         // Calculate Epsilon*MassFlowRate*Cp
    5618            4 :         if (NTU > MaxExpPower) {
    5619            0 :             Eff = 1.0;
    5620            0 :             calculateHXEffectivenessTerm = FlowFraction * WaterMassFlow * CpWater;
    5621              :         } else {
    5622            4 :             Eff = 1.0 - std::exp(-NTU);
    5623            4 :             calculateHXEffectivenessTerm = Eff * FlowFraction * WaterMassFlow * CpWater;
    5624              :         }
    5625              : 
    5626            4 :         return calculateHXEffectivenessTerm;
    5627            4 :     }
    5628              : 
    5629            1 :     Real64 HydronicSystemBaseData::calculateUFromISOStandard(EnergyPlusData &state,
    5630              :                                                              int const SurfNum,
    5631              :                                                              Real64 const WaterMassFlow,
    5632              :                                                              SystemType typeOfRadiantSystem,
    5633              :                                                              int const DesignObjPtr // Design Object Pointer
    5634              :     )
    5635              :     {
    5636              :         // Calculates the U-value for a pipe embedded in a radiant system using the information
    5637              :         // from ISO Standard 11855, Part 2 (2012): "Building environment design — Design, dimensioning,
    5638              :         // installation and control of embedded radiant heating and cooling systems — Part 2:
    5639              :         // Determination of the design heating and cooling capacity."  This looks exclusively at the heat transfer
    5640              :         // between the fluid and the inner side of the pipe and heat conduction through the pipe.  The remainder
    5641              :         // of the ISO calculation relates to the slab itself which is modeled using transient heat conduction here
    5642              :         // in EnergyPlus.
    5643              : 
    5644              :         // Return value
    5645              :         Real64 calculateUFromISOStandard;
    5646              : 
    5647            1 :         int constructionNumber = state.dataSurface->Surface(SurfNum).Construction;
    5648              : 
    5649            1 :         Real64 TubeDiameterOuter(0.0);
    5650            1 :         Real64 TubeDiameterInner(0.0);
    5651            1 :         Real64 TubeConductivity(0.0);
    5652              : 
    5653            1 :         if (typeOfRadiantSystem == SystemType::Hydronic) {
    5654              :             VarFlowRadDesignData variableFlowDesignDataObject{
    5655            0 :                 state.dataLowTempRadSys->HydronicRadiantSysDesign(DesignObjPtr)}; // Contains the data for variable flow hydronic systems
    5656            0 :             TubeDiameterOuter = variableFlowDesignDataObject.TubeDiameterOuter;
    5657            0 :             TubeDiameterInner = variableFlowDesignDataObject.TubeDiameterInner;
    5658            0 :             TubeConductivity = variableFlowDesignDataObject.VarFlowTubeConductivity;
    5659            0 :         }
    5660            1 :         if (typeOfRadiantSystem == SystemType::ConstantFlow) {
    5661              :             ConstantFlowRadDesignData constantFlowDesignDataObject{
    5662            1 :                 state.dataLowTempRadSys->CflowRadiantSysDesign(DesignObjPtr)}; // Contains the data for constant flow hydronic systems
    5663            1 :             TubeDiameterOuter = constantFlowDesignDataObject.TubeDiameterOuter;
    5664            1 :             TubeDiameterInner = constantFlowDesignDataObject.TubeDiameterInner;
    5665            1 :             TubeConductivity = constantFlowDesignDataObject.ConstFlowTubeConductivity;
    5666            1 :         }
    5667              : 
    5668              :         // Fluid resistance to heat transfer, assumes turbulent flow (Equation B5, p. 38 of ISO Standard 11855-2)
    5669            1 :         Real64 distanceBetweenPipes = 2.0 * state.dataConstruction->Construct(constructionNumber).ThicknessPerpend;
    5670            1 :         Real64 ratioDiameterToMassFlowLength = TubeDiameterInner / WaterMassFlow / this->TubeLength;
    5671            1 :         Real64 rFluid = 0.125 / Constant::Pi * std::pow(distanceBetweenPipes, 0.13) * std::pow(ratioDiameterToMassFlowLength, 0.87);
    5672              : 
    5673              :         // Resistance to heat transfer (conduction through the piping material, Equation B6, p. 38 of ISO Standard 11855-2)
    5674            1 :         Real64 rTube = 0.5 * distanceBetweenPipes * std::log(TubeDiameterOuter / TubeDiameterInner) / Constant::Pi / TubeConductivity;
    5675              : 
    5676            1 :         calculateUFromISOStandard = 1.0 / (rFluid + rTube);
    5677              : 
    5678            1 :         return calculateUFromISOStandard;
    5679              :     }
    5680              : 
    5681       249950 :     void UpdateRadSysSourceValAvg(EnergyPlusData &state,
    5682              :                                   bool &LowTempRadSysOn) // .TRUE. if the radiant system has run this zone time step
    5683              :     {
    5684              : 
    5685              :         // SUBROUTINE INFORMATION:
    5686              :         //       AUTHOR         Rick Strand
    5687              :         //       DATE WRITTEN   November 2000
    5688              : 
    5689              :         // PURPOSE OF THIS SUBROUTINE:
    5690              :         // To transfer the average value of the heat source/sink over the entire
    5691              :         // zone time step back to the heat balance routines so that the heat
    5692              :         // balance algorithms can simulate one last time with the average source
    5693              :         // to maintain some reasonable amount of continuity and energy balance
    5694              :         // in the temperature and flux histories.
    5695              : 
    5696              :         // METHODOLOGY EMPLOYED:
    5697              :         // All of the record keeping for the average term is done in the Update
    5698              :         // routine so the only other thing that this subroutine does is check to
    5699              :         // see if the system was even on.  If any average term is non-zero, then
    5700              :         // one or more of the radiant systems was running.
    5701              : 
    5702              :         // SUBROUTINE PARAMETER DEFINITIONS:
    5703       249950 :         Real64 constexpr CloseEnough(0.01); // Some arbitrarily small value to avoid zeros and numbers that are almost the same
    5704              : 
    5705              :         // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    5706              :         int SurfNum; // DO loop counter for surface index
    5707              : 
    5708       249950 :         LowTempRadSysOn = false;
    5709              : 
    5710              :         // If there are no radiant systems in this input file, just RETURN
    5711       249950 :         if (state.dataLowTempRadSys->TotalNumOfRadSystems == 0) return;
    5712              : 
    5713              :         // Now check to see if anything is running and transfer information from the "average" variables to
    5714              :         // the array that will be used within the heat balance.
    5715            4 :         state.dataHeatBalFanSys->QRadSysSource = 0.0; // Zero this out first
    5716            8 :         for (int numRadSys = 1; numRadSys <= state.dataLowTempRadSys->NumOfHydrLowTempRadSys; ++numRadSys) {
    5717            4 :             auto &thisLTR = state.dataLowTempRadSys->HydrRadSys(numRadSys);
    5718           10 :             for (int numRadSurf = 1; numRadSurf <= thisLTR.NumOfSurfaces; ++numRadSurf) {
    5719            6 :                 if (thisLTR.QRadSysSrcAvg(numRadSurf) != 0.0) LowTempRadSysOn = true;
    5720            6 :                 SurfNum = thisLTR.SurfacePtr(numRadSurf);
    5721            6 :                 state.dataHeatBalFanSys->QRadSysSource(SurfNum) = thisLTR.QRadSysSrcAvg(numRadSurf);
    5722              :             }
    5723              :         }
    5724            6 :         for (int numRadSys = 1; numRadSys <= state.dataLowTempRadSys->NumOfCFloLowTempRadSys; ++numRadSys) {
    5725            2 :             auto &thisLTR = state.dataLowTempRadSys->CFloRadSys(numRadSys);
    5726            4 :             for (int numRadSurf = 1; numRadSurf <= thisLTR.NumOfSurfaces; ++numRadSurf) {
    5727            2 :                 if (thisLTR.QRadSysSrcAvg(numRadSurf) != 0.0) LowTempRadSysOn = true;
    5728            2 :                 SurfNum = thisLTR.SurfacePtr(numRadSurf);
    5729            2 :                 state.dataHeatBalFanSys->QRadSysSource(SurfNum) = thisLTR.QRadSysSrcAvg(numRadSurf);
    5730              :             }
    5731              :         }
    5732            6 :         for (int numRadSys = 1; numRadSys <= state.dataLowTempRadSys->NumOfElecLowTempRadSys; ++numRadSys) {
    5733            2 :             auto &thisLTR = state.dataLowTempRadSys->ElecRadSys(numRadSys);
    5734            4 :             for (int numRadSurf = 1; numRadSurf <= thisLTR.NumOfSurfaces; ++numRadSurf) {
    5735            2 :                 if (thisLTR.QRadSysSrcAvg(numRadSurf) != 0.0) LowTempRadSysOn = true;
    5736            2 :                 SurfNum = thisLTR.SurfacePtr(numRadSurf);
    5737            2 :                 state.dataHeatBalFanSys->QRadSysSource(SurfNum) = thisLTR.QRadSysSrcAvg(numRadSurf);
    5738              :             }
    5739              :         }
    5740              : 
    5741            4 :         auto const &Surface = state.dataSurface->Surface;
    5742              : 
    5743              :         // For interzone surfaces, QRadSysSource was only updated for the "active" side.  The
    5744              :         // active side would have a non-zero value at this point.  If the numbers differ, then we have to manually update.
    5745           28 :         for (SurfNum = 1; SurfNum <= state.dataSurface->TotSurfaces; ++SurfNum) {
    5746           24 :             if (Surface(SurfNum).ExtBoundCond > 0 && Surface(SurfNum).ExtBoundCond != SurfNum) {
    5747            8 :                 if (std::abs(state.dataHeatBalFanSys->QRadSysSource(SurfNum) -
    5748            8 :                              state.dataHeatBalFanSys->QRadSysSource(Surface(SurfNum).ExtBoundCond)) > CloseEnough) { // numbers differ
    5749            4 :                     if (std::abs(state.dataHeatBalFanSys->QRadSysSource(SurfNum)) >
    5750            2 :                         std::abs(state.dataHeatBalFanSys->QRadSysSource(Surface(SurfNum).ExtBoundCond))) {
    5751            2 :                         state.dataHeatBalFanSys->QRadSysSource(Surface(SurfNum).ExtBoundCond) = state.dataHeatBalFanSys->QRadSysSource(SurfNum);
    5752              :                     } else {
    5753            0 :                         state.dataHeatBalFanSys->QRadSysSource(SurfNum) = state.dataHeatBalFanSys->QRadSysSource(Surface(SurfNum).ExtBoundCond);
    5754              :                     }
    5755              :                 }
    5756              :             }
    5757              :         }
    5758              :     }
    5759              : 
    5760            0 :     void VariableFlowRadiantSystemData::reportLowTemperatureRadiantSystem([[maybe_unused]] EnergyPlusData &state)
    5761              :     {
    5762              : 
    5763            0 :         auto &Zone = state.dataHeatBal->Zone;
    5764              : 
    5765              :         // Using/Aliasing
    5766            0 :         Real64 TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
    5767              : 
    5768            0 :         Real64 totalRadSysPower(0.0); // Total source/sink power for the radiant system (sum of all surfaces of the system)
    5769              : 
    5770            0 :         for (int radSurfNum = 1; radSurfNum <= this->NumOfSurfaces; ++radSurfNum) {
    5771            0 :             totalRadSysPower += state.dataHeatBalFanSys->QRadSysSource(this->SurfacePtr(radSurfNum));
    5772              :         }
    5773              : 
    5774            0 :         totalRadSysPower *= double(Zone(this->ZonePtr).Multiplier * Zone(this->ZonePtr).ListMultiplier);
    5775              : 
    5776            0 :         this->HeatPower = 0.0;
    5777            0 :         this->CoolPower = 0.0;
    5778              : 
    5779            0 :         if (this->opMode == OpMode::Heat) {
    5780            0 :             this->WaterInletTemp = state.dataLoopNodes->Node(this->HotWaterInNode).Temp;
    5781            0 :             this->WaterOutletTemp = state.dataLoopNodes->Node(this->HotWaterOutNode).Temp;
    5782            0 :             this->WaterMassFlowRate = state.dataLoopNodes->Node(this->HotWaterInNode).MassFlowRate;
    5783            0 :             this->HeatPower = totalRadSysPower;
    5784              : 
    5785            0 :         } else if (this->opMode == OpMode::Cool) {
    5786            0 :             this->WaterInletTemp = state.dataLoopNodes->Node(this->ColdWaterInNode).Temp;
    5787            0 :             this->WaterOutletTemp = state.dataLoopNodes->Node(this->ColdWaterOutNode).Temp;
    5788            0 :             this->WaterMassFlowRate = state.dataLoopNodes->Node(this->ColdWaterInNode).MassFlowRate;
    5789            0 :             this->CoolPower = -totalRadSysPower;
    5790              : 
    5791              :         } else { // Not Operating: Leave temperatures at previous values
    5792            0 :             this->WaterMassFlowRate = 0.0;
    5793            0 :             this->WaterOutletTemp = this->WaterInletTemp;
    5794              :         }
    5795              : 
    5796            0 :         this->HeatEnergy = this->HeatPower * TimeStepSysSec;
    5797            0 :         this->CoolEnergy = this->CoolPower * TimeStepSysSec;
    5798              : 
    5799            0 :         if (this->CondCausedShutDown) {
    5800            0 :             this->CondCausedTimeOff = TimeStepSysSec;
    5801              :         } else {
    5802            0 :             this->CondCausedTimeOff = 0.0;
    5803              :         }
    5804            0 :     }
    5805              : 
    5806            0 :     void ConstantFlowRadiantSystemData::reportLowTemperatureRadiantSystem(EnergyPlusData &state)
    5807              :     {
    5808              : 
    5809            0 :         auto &Zone = state.dataHeatBal->Zone;
    5810              : 
    5811              :         // Using/Aliasing
    5812            0 :         Real64 TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
    5813              : 
    5814            0 :         constexpr std::string_view routineName("ReportConstantFlowSystem");
    5815              :         Real64 cpFluid;               // Specific heat of the fluid in the radiant system
    5816            0 :         Real64 totalRadSysPower(0.0); // Total source/sink power for the radiant system (sum of all surfaces of the system)
    5817              : 
    5818            0 :         for (int radSurfNum = 1; radSurfNum <= this->NumOfSurfaces; ++radSurfNum) {
    5819            0 :             totalRadSysPower += state.dataHeatBalFanSys->QRadSysSource(this->SurfacePtr(radSurfNum));
    5820              :         }
    5821              : 
    5822            0 :         totalRadSysPower *= double(Zone(this->ZonePtr).Multiplier * Zone(this->ZonePtr).ListMultiplier);
    5823              : 
    5824            0 :         this->HeatPower = 0.0;
    5825            0 :         this->CoolPower = 0.0;
    5826              : 
    5827              :         // Note that temperatures have already been set as part of the simulation
    5828              :         // step.  So, they do not need to be calculated here except for the pump
    5829              :         // inlet temperature which was not calculated elsewhere.  If the system is
    5830              :         // not operating, leave the temperatures with their previous values but
    5831              :         // zero out the flow and power quantities (should have already been done
    5832              :         // in another routine, but just in case...).
    5833              : 
    5834            0 :         if (this->opMode == OpMode::Heat) {
    5835            0 :             cpFluid = state.dataPlnt->PlantLoop(this->HWPlantLoc.loopNum)
    5836            0 :                           .glycol->getSpecificHeat(state, state.dataLoopNodes->Node(this->HotWaterInNode).Temp, routineName);
    5837              : 
    5838            0 :             this->HeatPower = totalRadSysPower;
    5839            0 :             if (this->PumpMassFlowRate > 0.0) {
    5840            0 :                 this->PumpInletTemp = this->WaterInletTemp - (this->PumpHeattoFluid / (this->PumpMassFlowRate * cpFluid));
    5841              :             } else {
    5842            0 :                 this->PumpInletTemp = this->WaterInletTemp;
    5843              :             }
    5844              : 
    5845            0 :         } else if (this->opMode == OpMode::Cool) {
    5846            0 :             cpFluid = state.dataPlnt->PlantLoop(this->CWPlantLoc.loopNum)
    5847            0 :                           .glycol->getSpecificHeat(state, state.dataLoopNodes->Node(this->ColdWaterInNode).Temp, routineName);
    5848              : 
    5849            0 :             this->CoolPower = -totalRadSysPower;
    5850            0 :             this->PumpInletTemp = this->WaterInletTemp - (this->PumpHeattoFluid / (this->PumpMassFlowRate * cpFluid));
    5851              : 
    5852              :         } else { // Not Operating
    5853            0 :             this->WaterOutletTemp = this->WaterInletTemp;
    5854            0 :             this->PumpInletTemp = this->WaterInletTemp;
    5855            0 :             this->WaterMassFlowRate = 0.0;
    5856            0 :             this->WaterInjectionRate = 0.0;
    5857            0 :             this->WaterRecircRate = 0.0;
    5858            0 :             this->HeatPower = 0.0;
    5859            0 :             this->CoolPower = 0.0;
    5860            0 :             this->PumpPower = 0.0;
    5861            0 :             this->PumpMassFlowRate = 0.0;
    5862            0 :             this->PumpHeattoFluid = 0.0;
    5863              :         }
    5864              : 
    5865            0 :         this->HeatEnergy = this->HeatPower * TimeStepSysSec;
    5866            0 :         this->CoolEnergy = this->CoolPower * TimeStepSysSec;
    5867            0 :         this->PumpEnergy = this->PumpPower * TimeStepSysSec;
    5868            0 :         this->PumpHeattoFluidEnergy = this->PumpHeattoFluid * TimeStepSysSec;
    5869              : 
    5870            0 :         if (this->CondCausedShutDown) {
    5871            0 :             this->CondCausedTimeOff = TimeStepSysSec;
    5872              :         } else {
    5873            0 :             this->CondCausedTimeOff = 0.0;
    5874              :         }
    5875            0 :     }
    5876              : 
    5877            0 :     void ElectricRadiantSystemData::reportLowTemperatureRadiantSystem([[maybe_unused]] EnergyPlusData &state)
    5878              :     {
    5879              : 
    5880            0 :         auto &Zone = state.dataHeatBal->Zone;
    5881            0 :         Real64 TimeStepSysSec = state.dataHVACGlobal->TimeStepSysSec;
    5882              :         // Using/Aliasing
    5883            0 :         Real64 totalRadSysPower(0.0); // Total source/sink power for the radiant system (sum of all surfaces of the system)
    5884              : 
    5885            0 :         for (int radSurfNum = 1; radSurfNum <= this->NumOfSurfaces; ++radSurfNum) {
    5886            0 :             totalRadSysPower += state.dataHeatBalFanSys->QRadSysSource(this->SurfacePtr(radSurfNum));
    5887              :         }
    5888              : 
    5889            0 :         totalRadSysPower *= double(Zone(this->ZonePtr).Multiplier * Zone(this->ZonePtr).ListMultiplier);
    5890              : 
    5891            0 :         this->ElecPower = totalRadSysPower;
    5892            0 :         this->ElecEnergy = this->ElecPower * TimeStepSysSec;
    5893            0 :         this->HeatPower = this->ElecPower;
    5894            0 :         this->HeatEnergy = this->ElecEnergy;
    5895            0 :     }
    5896              : 
    5897              : } // namespace LowTempRadiantSystem
    5898              : 
    5899              : } // namespace EnergyPlus
        

Generated by: LCOV version 2.0-1