LCOV - code coverage report
Current view: top level - EnergyPlus - ChilledCeilingPanelSimple.cc (source / functions) Hit Total Coverage
Test: lcov.output.filtered Lines: 537 819 65.6 %
Date: 2023-01-17 19:17:23 Functions: 13 13 100.0 %

          Line data    Source code
       1             : // EnergyPlus, Copyright (c) 1996-2023, The Board of Trustees of the University of Illinois,
       2             : // The Regents of the University of California, through Lawrence Berkeley National Laboratory
       3             : // (subject to receipt of any required approvals from the U.S. Dept. of Energy), Oak Ridge
       4             : // National Laboratory, managed by UT-Battelle, Alliance for Sustainable Energy, LLC, and other
       5             : // contributors. All rights reserved.
       6             : //
       7             : // NOTICE: This Software was developed under funding from the U.S. Department of Energy and the
       8             : // U.S. Government consequently retains certain rights. As such, the U.S. Government has been
       9             : // granted for itself and others acting on its behalf a paid-up, nonexclusive, irrevocable,
      10             : // worldwide license in the Software to reproduce, distribute copies to the public, prepare
      11             : // derivative works, and perform publicly and display publicly, and to permit others to do so.
      12             : //
      13             : // Redistribution and use in source and binary forms, with or without modification, are permitted
      14             : // provided that the following conditions are met:
      15             : //
      16             : // (1) Redistributions of source code must retain the above copyright notice, this list of
      17             : //     conditions and the following disclaimer.
      18             : //
      19             : // (2) Redistributions in binary form must reproduce the above copyright notice, this list of
      20             : //     conditions and the following disclaimer in the documentation and/or other materials
      21             : //     provided with the distribution.
      22             : //
      23             : // (3) Neither the name of the University of California, Lawrence Berkeley National Laboratory,
      24             : //     the University of Illinois, U.S. Dept. of Energy nor the names of its contributors may be
      25             : //     used to endorse or promote products derived from this software without specific prior
      26             : //     written permission.
      27             : //
      28             : // (4) Use of EnergyPlus(TM) Name. If Licensee (i) distributes the software in stand-alone form
      29             : //     without changes from the version obtained under this License, or (ii) Licensee makes a
      30             : //     reference solely to the software portion of its product, Licensee must refer to the
      31             : //     software as "EnergyPlus version X" software, where "X" is the version number Licensee
      32             : //     obtained under this License and may not use a different name for the software. Except as
      33             : //     specifically required in this Section (4), Licensee shall not use in a company name, a
      34             : //     product name, in advertising, publicity, or other promotional activities any name, trade
      35             : //     name, trademark, logo, or other designation of "EnergyPlus", "E+", "e+" or confusingly
      36             : //     similar designation, without the U.S. Department of Energy's prior written consent.
      37             : //
      38             : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
      39             : // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
      40             : // AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
      41             : // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      42             : // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
      43             : // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      44             : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
      45             : // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      46             : // POSSIBILITY OF SUCH DAMAGE.
      47             : 
      48             : // C++ Headers
      49             : #include <cmath>
      50             : 
      51             : // ObjexxFCL Headers
      52             : #include <ObjexxFCL/Array.functions.hh>
      53             : #include <ObjexxFCL/Fmath.hh>
      54             : 
      55             : // EnergyPlus Headers
      56             : #include <EnergyPlus/Autosizing/CoolingCapacitySizing.hh>
      57             : #include <EnergyPlus/BranchNodeConnections.hh>
      58             : #include <EnergyPlus/ChilledCeilingPanelSimple.hh>
      59             : #include <EnergyPlus/Data/EnergyPlusData.hh>
      60             : #include <EnergyPlus/DataEnvironment.hh>
      61             : #include <EnergyPlus/DataHVACGlobals.hh>
      62             : #include <EnergyPlus/DataHeatBalFanSys.hh>
      63             : #include <EnergyPlus/DataHeatBalSurface.hh>
      64             : #include <EnergyPlus/DataHeatBalance.hh>
      65             : #include <EnergyPlus/DataIPShortCuts.hh>
      66             : #include <EnergyPlus/DataSizing.hh>
      67             : #include <EnergyPlus/DataSurfaces.hh>
      68             : #include <EnergyPlus/DataZoneEnergyDemands.hh>
      69             : #include <EnergyPlus/DataZoneEquipment.hh>
      70             : #include <EnergyPlus/FluidProperties.hh>
      71             : #include <EnergyPlus/GeneralRoutines.hh>
      72             : #include <EnergyPlus/HeatBalanceIntRadExchange.hh>
      73             : #include <EnergyPlus/HeatBalanceSurfaceManager.hh>
      74             : #include <EnergyPlus/InputProcessing/InputProcessor.hh>
      75             : #include <EnergyPlus/NodeInputManager.hh>
      76             : #include <EnergyPlus/OutputProcessor.hh>
      77             : #include <EnergyPlus/Plant/DataPlant.hh>
      78             : #include <EnergyPlus/PlantUtilities.hh>
      79             : #include <EnergyPlus/Psychrometrics.hh>
      80             : #include <EnergyPlus/ScheduleManager.hh>
      81             : #include <EnergyPlus/ZoneTempPredictorCorrector.hh>
      82             : 
      83             : namespace EnergyPlus::CoolingPanelSimple {
      84             : 
      85             : // Module -- (ref: Object: ZoneHVAC:CoolingPanel:RadiantConvective:Water)
      86             : 
      87             : // Module containing the routines dealing with the simple (chilled ceiling) cooling panels
      88             : 
      89             : // MODULE INFORMATION:
      90             : //       AUTHOR         Rick Strand
      91             : //       DATE WRITTEN   Aug 2014
      92             : 
      93             : // PURPOSE OF THIS MODULE:
      94             : // The purpose of this module is to simulate simple chilled ceiling panels.  It is similar to
      95             : // hot water radiant/convective baseboard units and the code for this model used that model as
      96             : // a starting point.
      97             : 
      98             : // REFERENCES:
      99             : // Existing code for hot water baseboard models (radiant-convective variety)
     100             : 
     101             : // USE STATEMENTS:
     102             : // MODULE PARAMETER DEFINITIONS
     103         771 : std::string const cCMO_CoolingPanel_Simple("ZoneHVAC:CoolingPanel:RadiantConvective:Water");
     104             : 
     105       22551 : void SimCoolingPanel(
     106             :     EnergyPlusData &state, std::string const &EquipName, int const ControlledZoneNum, bool const FirstHVACIteration, Real64 &PowerMet, int &CompIndex)
     107             : {
     108             : 
     109             :     // SUBROUTINE INFORMATION:
     110             :     //       AUTHOR         Rick Strand
     111             :     //       DATE WRITTEN   Aug 2014
     112             : 
     113             :     // PURPOSE OF THIS SUBROUTINE:
     114             :     // This subroutine simulates the simple cooling (chilled ceiling) panel.  It borrows heavily
     115             :     // from the hot water radiant-convective baseboard model code.
     116             : 
     117             :     // REFERENCES:
     118             :     // Existing code for hot water baseboard models (radiant-convective variety)
     119             : 
     120             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     121             :     int CoolingPanelNum; // Index of unit in baseboard array
     122             :     Real64 QZnReq;       // Zone load not yet satisfied
     123             :     Real64 MaxWaterFlow;
     124             :     Real64 MinWaterFlow;
     125             : 
     126       22551 :     if (state.dataChilledCeilingPanelSimple->GetInputFlag) {
     127           4 :         GetCoolingPanelInput(state);
     128           4 :         state.dataChilledCeilingPanelSimple->GetInputFlag = false;
     129             :     }
     130             : 
     131             :     // Find the correct Baseboard Equipment
     132       22551 :     if (CompIndex == 0) {
     133           8 :         CoolingPanelNum = UtilityRoutines::FindItemInList(EquipName,
     134           4 :                                                           state.dataChilledCeilingPanelSimple->CoolingPanel,
     135             :                                                           &CoolingPanelParams::EquipID,
     136           4 :                                                           (int)state.dataChilledCeilingPanelSimple->CoolingPanel.size());
     137           4 :         if (CoolingPanelNum == 0) {
     138           0 :             ShowFatalError(state, "SimCoolingPanelSimple: Unit not found=" + EquipName);
     139             :         }
     140           4 :         CompIndex = CoolingPanelNum;
     141             :     } else {
     142       22547 :         CoolingPanelNum = CompIndex;
     143       22547 :         if (CoolingPanelNum > (int)state.dataChilledCeilingPanelSimple->CoolingPanel.size() || CoolingPanelNum < 1) {
     144           0 :             ShowFatalError(state,
     145           0 :                            format("SimCoolingPanelSimple:  Invalid CompIndex passed={}, Number of Units={}, Entered Unit name={}",
     146             :                                   CoolingPanelNum,
     147           0 :                                   (int)state.dataChilledCeilingPanelSimple->CoolingPanel.size(),
     148           0 :                                   EquipName));
     149             :         }
     150       22547 :         if (state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum).CheckEquipName) {
     151           4 :             if (EquipName != state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum).EquipID) {
     152           0 :                 ShowFatalError(state,
     153           0 :                                format("SimCoolingPanelSimple: Invalid CompIndex passed={}, Unit name={}, stored Unit Name for that index={}",
     154             :                                       CoolingPanelNum,
     155             :                                       EquipName,
     156           0 :                                       state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum).EquipID));
     157             :             }
     158           4 :             state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum).CheckEquipName = false;
     159             :         }
     160             :     }
     161             : 
     162       22551 :     if (CompIndex > 0) {
     163             : 
     164       22551 :         auto &ThisCP(state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum));
     165             : 
     166       22551 :         InitCoolingPanel(state, CoolingPanelNum, ControlledZoneNum, FirstHVACIteration);
     167             : 
     168       22551 :         QZnReq = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ControlledZoneNum).RemainingOutputReqToCoolSP;
     169             : 
     170             :         // On the first HVAC iteration the system values are given to the controller, but after that
     171             :         // the demand limits are in place and there needs to be feedback to the Zone Equipment
     172       22551 :         if (FirstHVACIteration) {
     173       10333 :             MaxWaterFlow = ThisCP.WaterMassFlowRateMax;
     174       10333 :             MinWaterFlow = 0.0;
     175             :         } else {
     176       12218 :             MaxWaterFlow = state.dataLoopNodes->Node(ThisCP.WaterInletNode).MassFlowRateMaxAvail;
     177       12218 :             MinWaterFlow = state.dataLoopNodes->Node(ThisCP.WaterInletNode).MassFlowRateMinAvail;
     178             :         }
     179             : 
     180       22551 :         switch (ThisCP.EquipType) {
     181       22551 :         case DataPlant::PlantEquipmentType::CoolingPanel_Simple: { // 'ZoneHVAC:CoolingPanel:RadiantConvective:Water'
     182       22551 :             ThisCP.CalcCoolingPanel(state, CoolingPanelNum);
     183       22551 :         } break;
     184           0 :         default: {
     185           0 :             ShowSevereError(
     186           0 :                 state, "SimCoolingPanelSimple: Errors in CoolingPanel=" + state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum).EquipID);
     187           0 :             ShowContinueError(
     188             :                 state,
     189           0 :                 format("Invalid or unimplemented equipment type={}", state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum).EquipType));
     190           0 :             ShowFatalError(state, "Preceding condition causes termination.");
     191           0 :         } break;
     192             :         }
     193             : 
     194       22551 :         PowerMet = ThisCP.TotPower;
     195             : 
     196       22551 :         UpdateCoolingPanel(state, CoolingPanelNum);
     197             : 
     198       22551 :         state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum).ReportCoolingPanel(state);
     199             : 
     200             :     } else {
     201           0 :         ShowFatalError(state, "SimCoolingPanelSimple: Unit not found=" + EquipName);
     202             :     }
     203       22551 : }
     204             : 
     205           4 : void GetCoolingPanelInput(EnergyPlusData &state)
     206             : {
     207             : 
     208             :     // SUBROUTINE INFORMATION:
     209             :     //       AUTHOR         Rick Strand
     210             :     //       DATE WRITTEN   Aug 2014
     211             : 
     212             :     // PURPOSE OF THIS SUBROUTINE:
     213             :     // This subroutine gets the input for the simple cooling panel units.
     214             : 
     215             :     // METHODOLOGY EMPLOYED:
     216             :     // Standard input processor calls--started from Daeho's radiant-convective water baseboard model.
     217             : 
     218             :     // Using/Aliasing
     219             :     using BranchNodeConnections::TestCompSet;
     220             :     using DataLoopNode::ObjectIsNotParent;
     221             :     using NodeInputManager::GetOnlySingleNode;
     222             :     using ScheduleManager::GetScheduleIndex;
     223             : 
     224             :     // SUBROUTINE PARAMETER DEFINITIONS:
     225             :     static constexpr std::string_view RoutineName("GetCoolingPanelInput:");
     226           4 :     Real64 constexpr MaxFraction(1.0);
     227           4 :     Real64 constexpr MinFraction(0.0);
     228           4 :     Real64 constexpr MaxWaterTempAvg(30.0);       // Maximum limit of average water temperature in degree C
     229           4 :     Real64 constexpr MinWaterTempAvg(0.0);        // Minimum limit of average water temperature in degree C
     230           4 :     Real64 constexpr MaxWaterFlowRate(10.0);      // Maximum limit of water volume flow rate in m3/s
     231           4 :     Real64 constexpr MinWaterFlowRate(0.00001);   // Minimum limit of water volume flow rate in m3/s
     232           4 :     Real64 constexpr WaterMassFlowDefault(0.063); // Default water mass flow rate in kg/s
     233           4 :     int constexpr MinDistribSurfaces(1);          // Minimum number of surfaces that a baseboard heater can radiate to
     234           4 :     Real64 constexpr MinThrottlingRange(0.5);     // Smallest throttling range allowed in degrees Celsius
     235             :     static constexpr std::string_view MeanAirTemperature("MeanAirTemperature");
     236             :     static constexpr std::string_view MeanRadiantTemperature("MeanRadiantTemperature");
     237             :     static constexpr std::string_view OperativeTemperature("OperativeTemperature");
     238             :     static constexpr std::string_view OutsideAirDryBulbTemperature("OutdoorDryBulbTemperature");
     239             :     static constexpr std::string_view OutsideAirWetBulbTemperature("OutdoorWetBulbTemperature");
     240             :     static constexpr std::string_view ZoneTotalLoad("ZoneTotalLoad");
     241             :     static constexpr std::string_view ZoneConvectiveLoad("ZoneConvectiveLoad");
     242             :     static constexpr std::string_view Off("Off");
     243             :     static constexpr std::string_view SimpleOff("SimpleOff");
     244             :     static constexpr std::string_view VariableOff("VariableOff");
     245             : 
     246             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     247             :     Real64 AllFracsSummed; // Sum of the fractions radiant
     248             :     int CoolingPanelNum;   // Cooling panel number
     249             :     int CoolPanelNumI;     // For loop index
     250             :     int NumAlphas;         // Number of Alphas for each GetobjectItem call
     251             :     int NumNumbers;        // Number of Numbers for each GetobjectItem call
     252             :     int SurfNum;           // Surface number Do loop counter
     253             :     int IOStat;
     254           4 :     bool ErrorsFound(false); // If errors detected in input
     255           4 :     auto &cCurrentModuleObject = state.dataIPShortCut->cCurrentModuleObject;
     256           4 :     int NumCoolingPanels = state.dataInputProcessing->inputProcessor->getNumObjectsFound(state, cCMO_CoolingPanel_Simple);
     257             : 
     258             :     // Count total number of baseboard units
     259             : 
     260           4 :     state.dataChilledCeilingPanelSimple->CoolingPanel.allocate(NumCoolingPanels);
     261             : 
     262             :     // Get the data from the user input related to cooling panels
     263           8 :     for (CoolingPanelNum = 1; CoolingPanelNum <= NumCoolingPanels; ++CoolingPanelNum) {
     264             : 
     265          28 :         state.dataInputProcessing->inputProcessor->getObjectItem(state,
     266             :                                                                  cCMO_CoolingPanel_Simple,
     267             :                                                                  CoolingPanelNum,
     268           4 :                                                                  state.dataIPShortCut->cAlphaArgs,
     269             :                                                                  NumAlphas,
     270           4 :                                                                  state.dataIPShortCut->rNumericArgs,
     271             :                                                                  NumNumbers,
     272             :                                                                  IOStat,
     273           4 :                                                                  state.dataIPShortCut->lNumericFieldBlanks,
     274           4 :                                                                  state.dataIPShortCut->lAlphaFieldBlanks,
     275           4 :                                                                  state.dataIPShortCut->cAlphaFieldNames,
     276           4 :                                                                  state.dataIPShortCut->cNumericFieldNames);
     277           4 :         UtilityRoutines::IsNameEmpty(state, state.dataIPShortCut->cAlphaArgs(1), cCurrentModuleObject, ErrorsFound);
     278             : 
     279           4 :         state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum).FieldNames.allocate(NumNumbers);
     280           4 :         state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum).FieldNames = "";
     281           4 :         state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum).FieldNames = state.dataIPShortCut->cNumericFieldNames;
     282             : 
     283           4 :         if (CoolingPanelNum > 1) {
     284           0 :             for (CoolPanelNumI = 2; CoolPanelNumI <= NumCoolingPanels; ++CoolPanelNumI) {
     285           0 :                 if (state.dataIPShortCut->cAlphaArgs(1) == state.dataChilledCeilingPanelSimple->CoolingPanel(CoolPanelNumI).EquipID) {
     286           0 :                     ErrorsFound = true;
     287           0 :                     ShowSevereError(state, state.dataIPShortCut->cAlphaArgs(1) + " is used as a name for more than one simple COOLING PANEL.");
     288           0 :                     ShowContinueError(state, "This is not allowed.");
     289             :                 }
     290             :             }
     291             :         }
     292             : 
     293           4 :         auto &ThisCP(state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum));
     294           4 :         ThisCP.EquipID = state.dataIPShortCut->cAlphaArgs(1);                  // Name of this simple cooling panel
     295           4 :         ThisCP.EquipType = DataPlant::PlantEquipmentType::CoolingPanel_Simple; //'ZoneHVAC:CoolingPanel:RadiantConvective:Water'
     296             : 
     297             :         // Get schedule
     298           4 :         ThisCP.Schedule = state.dataIPShortCut->cAlphaArgs(2);
     299           4 :         if (state.dataIPShortCut->lAlphaFieldBlanks(2)) {
     300           0 :             ThisCP.SchedPtr = DataGlobalConstants::ScheduleAlwaysOn;
     301             :         } else {
     302           4 :             ThisCP.SchedPtr = GetScheduleIndex(state, state.dataIPShortCut->cAlphaArgs(2));
     303           4 :             if (ThisCP.SchedPtr == 0) {
     304           0 :                 ShowSevereError(state,
     305           0 :                                 std::string{RoutineName} + cCMO_CoolingPanel_Simple + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", " +
     306           0 :                                     state.dataIPShortCut->cAlphaFieldNames(2) + "=\"" + state.dataIPShortCut->cAlphaArgs(2) + "\" not found.");
     307           0 :                 ErrorsFound = true;
     308             :             }
     309             :         }
     310             : 
     311             :         // Get inlet node number
     312           4 :         ThisCP.WaterInletNode = GetOnlySingleNode(state,
     313           4 :                                                   state.dataIPShortCut->cAlphaArgs(3),
     314             :                                                   ErrorsFound,
     315             :                                                   DataLoopNode::ConnectionObjectType::ZoneHVACCoolingPanelRadiantConvectiveWater,
     316           4 :                                                   state.dataIPShortCut->cAlphaArgs(1),
     317             :                                                   DataLoopNode::NodeFluidType::Water,
     318             :                                                   DataLoopNode::ConnectionType::Inlet,
     319             :                                                   NodeInputManager::CompFluidStream::Primary,
     320           4 :                                                   ObjectIsNotParent);
     321             : 
     322             :         // Get outlet node number
     323           4 :         ThisCP.WaterOutletNode = GetOnlySingleNode(state,
     324           4 :                                                    state.dataIPShortCut->cAlphaArgs(4),
     325             :                                                    ErrorsFound,
     326             :                                                    DataLoopNode::ConnectionObjectType::ZoneHVACCoolingPanelRadiantConvectiveWater,
     327           4 :                                                    state.dataIPShortCut->cAlphaArgs(1),
     328             :                                                    DataLoopNode::NodeFluidType::Water,
     329             :                                                    DataLoopNode::ConnectionType::Outlet,
     330             :                                                    NodeInputManager::CompFluidStream::Primary,
     331           4 :                                                    ObjectIsNotParent);
     332           8 :         TestCompSet(state,
     333             :                     cCMO_CoolingPanel_Simple,
     334           4 :                     state.dataIPShortCut->cAlphaArgs(1),
     335           4 :                     state.dataIPShortCut->cAlphaArgs(3),
     336           4 :                     state.dataIPShortCut->cAlphaArgs(4),
     337             :                     "Chilled Water Nodes");
     338             : 
     339           4 :         ThisCP.RatedWaterTemp = state.dataIPShortCut->rNumericArgs(1);
     340           4 :         if (ThisCP.RatedWaterTemp > MaxWaterTempAvg + 0.001) {
     341           0 :             ShowWarningError(state,
     342           0 :                              std::string{RoutineName} + cCMO_CoolingPanel_Simple + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", " +
     343           0 :                                  state.dataIPShortCut->cNumericFieldNames(1) + " was higher than the allowable maximum.");
     344           0 :             ShowContinueError(state, format("...reset to maximum value=[{:.2R}].", MaxWaterTempAvg));
     345           0 :             ThisCP.RatedWaterTemp = MaxWaterTempAvg;
     346           4 :         } else if (ThisCP.RatedWaterTemp < MinWaterTempAvg - 0.001) {
     347           0 :             ShowWarningError(state,
     348           0 :                              std::string{RoutineName} + cCMO_CoolingPanel_Simple + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", " +
     349           0 :                                  state.dataIPShortCut->cNumericFieldNames(1) + " was lower than the allowable minimum.");
     350           0 :             ShowContinueError(state, format("...reset to minimum value=[{:.2R}].", MinWaterTempAvg));
     351           0 :             ThisCP.RatedWaterTemp = MinWaterTempAvg;
     352             :         }
     353             : 
     354           4 :         ThisCP.RatedZoneAirTemp = state.dataIPShortCut->rNumericArgs(2);
     355           4 :         if (ThisCP.RatedZoneAirTemp > MaxWaterTempAvg + 0.001) {
     356           0 :             ShowWarningError(state,
     357           0 :                              std::string{RoutineName} + cCMO_CoolingPanel_Simple + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", " +
     358           0 :                                  state.dataIPShortCut->cNumericFieldNames(2) + " was higher than the allowable maximum.");
     359           0 :             ShowContinueError(state, format("...reset to maximum value=[{:.2R}].", MaxWaterTempAvg));
     360           0 :             ThisCP.RatedZoneAirTemp = MaxWaterTempAvg;
     361           4 :         } else if (ThisCP.RatedZoneAirTemp < MinWaterTempAvg - 0.001) {
     362           0 :             ShowWarningError(state,
     363           0 :                              std::string{RoutineName} + cCMO_CoolingPanel_Simple + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", " +
     364           0 :                                  state.dataIPShortCut->cNumericFieldNames(2) + " was lower than the allowable minimum.");
     365           0 :             ShowContinueError(state, format("...reset to minimum value=[{:.2R}].", MinWaterTempAvg));
     366           0 :             ThisCP.RatedZoneAirTemp = MinWaterTempAvg;
     367             :         }
     368             : 
     369           4 :         ThisCP.RatedWaterFlowRate = state.dataIPShortCut->rNumericArgs(3);
     370           4 :         if (ThisCP.RatedWaterFlowRate < 0.00001 || ThisCP.RatedWaterFlowRate > 10.0) {
     371           0 :             ShowWarningError(state,
     372           0 :                              std::string{RoutineName} + cCMO_CoolingPanel_Simple + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", " +
     373           0 :                                  state.dataIPShortCut->cNumericFieldNames(2) + " is an invalid Standard Water mass flow rate.");
     374           0 :             ShowContinueError(state, format("...reset to a default value=[{:.1R}].", WaterMassFlowDefault));
     375           0 :             ThisCP.RatedWaterFlowRate = WaterMassFlowDefault;
     376             :         }
     377             : 
     378           4 :         if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(5), "CoolingDesignCapacity")) {
     379           2 :             ThisCP.CoolingCapMethod = DataSizing::CoolingDesignCapacity;
     380           2 :             if (!state.dataIPShortCut->lNumericFieldBlanks(4)) {
     381           2 :                 ThisCP.ScaledCoolingCapacity = state.dataIPShortCut->rNumericArgs(4);
     382           2 :                 if (ThisCP.ScaledCoolingCapacity < 0.0 && ThisCP.ScaledCoolingCapacity != DataSizing::AutoSize) {
     383           0 :                     ShowSevereError(state, cCMO_CoolingPanel_Simple + " = " + ThisCP.EquipID);
     384           0 :                     ShowContinueError(
     385           0 :                         state, format("Illegal {} = {:.7T}", state.dataIPShortCut->cNumericFieldNames(4), state.dataIPShortCut->rNumericArgs(4)));
     386           0 :                     ErrorsFound = true;
     387             :                 }
     388             :             } else {
     389           0 :                 if ((!state.dataIPShortCut->lAlphaFieldBlanks(6)) || (!state.dataIPShortCut->lAlphaFieldBlanks(7))) {
     390           0 :                     ShowSevereError(state, cCMO_CoolingPanel_Simple + " = " + ThisCP.EquipID);
     391           0 :                     ShowContinueError(state, "Input for " + state.dataIPShortCut->cAlphaFieldNames(5) + " = " + state.dataIPShortCut->cAlphaArgs(5));
     392           0 :                     ShowContinueError(state, "Blank field not allowed for " + state.dataIPShortCut->cNumericFieldNames(4));
     393           0 :                     ErrorsFound = true;
     394             :                 }
     395             :             }
     396           2 :         } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(5), "CapacityPerFloorArea")) {
     397           1 :             ThisCP.CoolingCapMethod = DataSizing::CapacityPerFloorArea;
     398           1 :             if (!state.dataIPShortCut->lNumericFieldBlanks(5)) {
     399           1 :                 ThisCP.ScaledCoolingCapacity = state.dataIPShortCut->rNumericArgs(5);
     400           1 :                 if (ThisCP.ScaledCoolingCapacity < 0.0) {
     401           0 :                     ShowSevereError(state, cCMO_CoolingPanel_Simple + " = " + ThisCP.EquipID);
     402           0 :                     ShowContinueError(state, "Input for " + state.dataIPShortCut->cAlphaFieldNames(5) + " = " + state.dataIPShortCut->cAlphaArgs(5));
     403           0 :                     ShowContinueError(
     404           0 :                         state, format("Illegal {} = {:.7T}", state.dataIPShortCut->cNumericFieldNames(5), state.dataIPShortCut->rNumericArgs(5)));
     405           0 :                     ErrorsFound = true;
     406           1 :                 } else if (ThisCP.ScaledCoolingCapacity == DataSizing::AutoSize) {
     407           0 :                     ShowSevereError(state, cCMO_CoolingPanel_Simple + " = " + ThisCP.EquipID);
     408           0 :                     ShowContinueError(state, "Input for " + state.dataIPShortCut->cAlphaFieldNames(5) + " = " + state.dataIPShortCut->cAlphaArgs(5));
     409           0 :                     ShowContinueError(state, "Illegal " + state.dataIPShortCut->cNumericFieldNames(5) + " = Autosize");
     410           0 :                     ErrorsFound = true;
     411             :                 }
     412             :             } else {
     413           0 :                 ShowSevereError(state, cCMO_CoolingPanel_Simple + " = " + ThisCP.EquipID);
     414           0 :                 ShowContinueError(state, "Input for " + state.dataIPShortCut->cAlphaFieldNames(5) + " = " + state.dataIPShortCut->cAlphaArgs(5));
     415           0 :                 ShowContinueError(state, "Blank field not allowed for " + state.dataIPShortCut->cNumericFieldNames(5));
     416           0 :                 ErrorsFound = true;
     417             :             }
     418           1 :         } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(5), "FractionOfAutosizedCoolingCapacity")) {
     419           1 :             ThisCP.CoolingCapMethod = DataSizing::FractionOfAutosizedCoolingCapacity;
     420           1 :             if (!state.dataIPShortCut->lNumericFieldBlanks(6)) {
     421           1 :                 ThisCP.ScaledCoolingCapacity = state.dataIPShortCut->rNumericArgs(6);
     422           1 :                 if (ThisCP.ScaledCoolingCapacity < 0.0) {
     423           0 :                     ShowSevereError(state, cCMO_CoolingPanel_Simple + " = " + ThisCP.EquipID);
     424           0 :                     ShowContinueError(
     425           0 :                         state, format("Illegal {} = {:.7T}", state.dataIPShortCut->cNumericFieldNames(6), state.dataIPShortCut->rNumericArgs(6)));
     426           0 :                     ErrorsFound = true;
     427             :                 }
     428             :             } else {
     429           0 :                 ShowSevereError(state, cCMO_CoolingPanel_Simple + " = " + ThisCP.EquipID);
     430           0 :                 ShowContinueError(state, "Input for " + state.dataIPShortCut->cAlphaFieldNames(5) + " = " + state.dataIPShortCut->cAlphaArgs(5));
     431           0 :                 ShowContinueError(state, "Blank field not allowed for " + state.dataIPShortCut->cNumericFieldNames(6));
     432           0 :                 ErrorsFound = true;
     433             :             }
     434             :         } else {
     435           0 :             ShowSevereError(state, cCMO_CoolingPanel_Simple + " = " + ThisCP.EquipID);
     436           0 :             ShowContinueError(state, "Illegal " + state.dataIPShortCut->cAlphaFieldNames(5) + " = " + state.dataIPShortCut->cAlphaArgs(5));
     437           0 :             ErrorsFound = true;
     438             :         }
     439             : 
     440           4 :         ThisCP.WaterVolFlowRateMax = state.dataIPShortCut->rNumericArgs(7);
     441           4 :         if ((ThisCP.WaterVolFlowRateMax <= MinWaterFlowRate) && ThisCP.WaterVolFlowRateMax != DataSizing::AutoSize) {
     442           0 :             ShowWarningError(state,
     443           0 :                              std::string{RoutineName} + cCMO_CoolingPanel_Simple + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", " +
     444           0 :                                  state.dataIPShortCut->cNumericFieldNames(7) + " was less than the allowable minimum.");
     445           0 :             ShowContinueError(state, format("...reset to minimum value=[{:.2R}].", MinWaterFlowRate));
     446           0 :             ThisCP.WaterVolFlowRateMax = MinWaterFlowRate;
     447           4 :         } else if (ThisCP.WaterVolFlowRateMax > MaxWaterFlowRate) {
     448           0 :             ShowWarningError(state,
     449           0 :                              std::string{RoutineName} + cCMO_CoolingPanel_Simple + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", " +
     450           0 :                                  state.dataIPShortCut->cNumericFieldNames(7) + " was higher than the allowable maximum.");
     451           0 :             ShowContinueError(state, format("...reset to maximum value=[{:.2R}].", MaxWaterFlowRate));
     452           0 :             ThisCP.WaterVolFlowRateMax = MaxWaterFlowRate;
     453             :         }
     454             : 
     455             :         // Process the temperature control type
     456           4 :         if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(6), MeanAirTemperature)) {
     457           3 :             ThisCP.controlType = ClgPanelCtrlType::MAT;
     458           1 :         } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(6), MeanRadiantTemperature)) {
     459           0 :             ThisCP.controlType = ClgPanelCtrlType::MRT;
     460           1 :         } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(6), OperativeTemperature)) {
     461           0 :             ThisCP.controlType = ClgPanelCtrlType::Operative;
     462           1 :         } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(6), OutsideAirDryBulbTemperature)) {
     463           0 :             ThisCP.controlType = ClgPanelCtrlType::ODB;
     464           1 :         } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(6), OutsideAirWetBulbTemperature)) {
     465           0 :             ThisCP.controlType = ClgPanelCtrlType::OWB;
     466           1 :         } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(6), ZoneTotalLoad)) {
     467           1 :             ThisCP.controlType = ClgPanelCtrlType::ZoneTotalLoad;
     468           0 :         } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(6), ZoneConvectiveLoad)) {
     469           0 :             ThisCP.controlType = ClgPanelCtrlType::ZoneConvectiveLoad;
     470             :         } else {
     471           0 :             ShowWarningError(state, "Invalid " + state.dataIPShortCut->cAlphaFieldNames(6) + " =" + state.dataIPShortCut->cAlphaArgs(6));
     472           0 :             ShowContinueError(state, "Occurs in " + std::string{RoutineName} + " = " + state.dataIPShortCut->cAlphaArgs(1));
     473           0 :             ShowContinueError(state, "Control reset to MAT control for this Simple Cooling Panel.");
     474           0 :             ThisCP.controlType = ClgPanelCtrlType::MAT;
     475             :         }
     476             : 
     477           4 :         ThisCP.ColdThrottlRange = state.dataIPShortCut->rNumericArgs(8);
     478           4 :         if (ThisCP.ColdThrottlRange < MinThrottlingRange) {
     479           0 :             ShowWarningError(state, cCMO_CoolingPanel_Simple + "Cooling throttling range too small, reset to 0.5");
     480           0 :             ShowContinueError(state, "Occurs in Cooling Panel=" + ThisCP.EquipID);
     481           0 :             ThisCP.ColdThrottlRange = MinThrottlingRange;
     482             :         }
     483             : 
     484           4 :         ThisCP.ColdSetptSched = state.dataIPShortCut->cAlphaArgs(7);
     485           4 :         ThisCP.ColdSetptSchedPtr = GetScheduleIndex(state, ThisCP.ColdSetptSched);
     486           4 :         if ((ThisCP.ColdSetptSchedPtr == 0) && (!state.dataIPShortCut->lAlphaFieldBlanks(7))) {
     487           0 :             ShowSevereError(state, state.dataIPShortCut->cAlphaFieldNames(7) + " not found: " + ThisCP.ColdSetptSched);
     488           0 :             ShowContinueError(state, "Occurs in " + std::string{RoutineName} + " = " + state.dataIPShortCut->cAlphaArgs(1));
     489           0 :             ErrorsFound = true;
     490             :         }
     491             : 
     492           4 :         if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(8), Off)) {
     493           3 :             ThisCP.CondCtrlType = CondCtrl::NONE;
     494           1 :         } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(8), SimpleOff)) {
     495           0 :             ThisCP.CondCtrlType = CondCtrl::SIMPLEOFF;
     496           1 :         } else if (UtilityRoutines::SameString(state.dataIPShortCut->cAlphaArgs(8), VariableOff)) {
     497           1 :             ThisCP.CondCtrlType = CondCtrl::VARIEDOFF;
     498             :         } else {
     499           0 :             ThisCP.CondCtrlType = CondCtrl::SIMPLEOFF;
     500             :         }
     501             : 
     502           4 :         ThisCP.CondDewPtDeltaT = state.dataIPShortCut->rNumericArgs(9);
     503             : 
     504           4 :         ThisCP.FracRadiant = state.dataIPShortCut->rNumericArgs(10);
     505           4 :         if (ThisCP.FracRadiant < MinFraction) {
     506           0 :             ShowWarningError(state,
     507           0 :                              std::string{RoutineName} + cCMO_CoolingPanel_Simple + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", " +
     508           0 :                                  state.dataIPShortCut->cNumericFieldNames(10) + " was lower than the allowable minimum.");
     509           0 :             ShowContinueError(state, format("...reset to minimum value=[{:.2R}].", MinFraction));
     510           0 :             ThisCP.FracRadiant = MinFraction;
     511             :         }
     512           4 :         if (ThisCP.FracRadiant > MaxFraction) {
     513           0 :             ShowWarningError(state,
     514           0 :                              std::string{RoutineName} + cCMO_CoolingPanel_Simple + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", " +
     515           0 :                                  state.dataIPShortCut->cNumericFieldNames(10) + " was higher than the allowable maximum.");
     516           0 :             ShowContinueError(state, format("...reset to maximum value=[{:.2R}].", MaxFraction));
     517           0 :             ThisCP.FracRadiant = MaxFraction;
     518             :         }
     519             : 
     520             :         // Remaining fraction is added to the zone as convective heat transfer
     521           4 :         AllFracsSummed = ThisCP.FracRadiant;
     522           4 :         if (AllFracsSummed > MaxFraction) {
     523           0 :             ShowWarningError(state,
     524           0 :                              std::string{RoutineName} + cCMO_CoolingPanel_Simple + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
     525             :                                  "\", Fraction Radiant was higher than the allowable maximum.");
     526           0 :             ThisCP.FracRadiant = MaxFraction;
     527           0 :             ThisCP.FracConvect = 0.0;
     528             :         } else {
     529           4 :             ThisCP.FracConvect = 1.0 - AllFracsSummed;
     530             :         }
     531             : 
     532           4 :         ThisCP.FracDistribPerson = state.dataIPShortCut->rNumericArgs(11);
     533           4 :         if (ThisCP.FracDistribPerson < MinFraction) {
     534           0 :             ShowWarningError(state,
     535           0 :                              std::string{RoutineName} + cCMO_CoolingPanel_Simple + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", " +
     536           0 :                                  state.dataIPShortCut->cNumericFieldNames(11) + " was lower than the allowable minimum.");
     537           0 :             ShowContinueError(state, format("...reset to minimum value=[{:.3R}].", MinFraction));
     538           0 :             ThisCP.FracDistribPerson = MinFraction;
     539             :         }
     540           4 :         if (ThisCP.FracDistribPerson > MaxFraction) {
     541           0 :             ShowWarningError(state,
     542           0 :                              std::string{RoutineName} + cCMO_CoolingPanel_Simple + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", " +
     543           0 :                                  state.dataIPShortCut->cNumericFieldNames(11) + " was higher than the allowable maximum.");
     544           0 :             ShowContinueError(state, format("...reset to maximum value=[{:.3R}].", MaxFraction));
     545           0 :             ThisCP.FracDistribPerson = MaxFraction;
     546             :         }
     547             : 
     548           4 :         ThisCP.TotSurfToDistrib = NumNumbers - 11;
     549           4 :         if ((ThisCP.TotSurfToDistrib < MinDistribSurfaces) && (ThisCP.FracRadiant > MinFraction)) {
     550           0 :             ShowSevereError(state,
     551           0 :                             std::string{RoutineName} + cCMO_CoolingPanel_Simple + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
     552             :                                 "\", the number of surface/radiant fraction groups entered was less than the allowable minimum.");
     553           0 :             ShowContinueError(state, format("...the minimum that must be entered=[{}].", MinDistribSurfaces));
     554           0 :             ErrorsFound = true;
     555           0 :             ThisCP.TotSurfToDistrib = 0; // error
     556             :         }
     557             : 
     558           4 :         ThisCP.SurfaceName.allocate(ThisCP.TotSurfToDistrib);
     559           4 :         ThisCP.SurfaceName = "";
     560           4 :         ThisCP.SurfacePtr.allocate(ThisCP.TotSurfToDistrib);
     561           4 :         ThisCP.SurfacePtr = 0;
     562           4 :         ThisCP.FracDistribToSurf.allocate(ThisCP.TotSurfToDistrib);
     563           4 :         ThisCP.FracDistribToSurf = 0.0;
     564             : 
     565             :         // search zone equipment list structure for zone index
     566          28 :         for (int ctrlZone = 1; ctrlZone <= state.dataGlobal->NumOfZones; ++ctrlZone) {
     567          56 :             for (int zoneEquipTypeNum = 1; zoneEquipTypeNum <= state.dataZoneEquip->ZoneEquipList(ctrlZone).NumOfEquipTypes; ++zoneEquipTypeNum) {
     568          36 :                 if (state.dataZoneEquip->ZoneEquipList(ctrlZone).EquipTypeEnum(zoneEquipTypeNum) == DataZoneEquipment::ZoneEquip::CoolingPanel &&
     569           4 :                     state.dataZoneEquip->ZoneEquipList(ctrlZone).EquipName(zoneEquipTypeNum) == ThisCP.EquipID) {
     570           4 :                     ThisCP.ZonePtr = ctrlZone;
     571             :                 }
     572             :             }
     573             :         }
     574           4 :         if (ThisCP.ZonePtr <= 0) {
     575           0 :             ShowSevereError(
     576           0 :                 state, std::string{RoutineName} + cCMO_CoolingPanel_Simple + "=\"" + ThisCP.EquipID + "\" is not on any ZoneHVAC:EquipmentList.");
     577           0 :             ErrorsFound = true;
     578           0 :             continue;
     579             :         }
     580             : 
     581           4 :         AllFracsSummed = ThisCP.FracDistribPerson;
     582          16 :         for (SurfNum = 1; SurfNum <= ThisCP.TotSurfToDistrib; ++SurfNum) {
     583          12 :             ThisCP.SurfaceName(SurfNum) = state.dataIPShortCut->cAlphaArgs(SurfNum + 8);
     584          12 :             ThisCP.SurfacePtr(SurfNum) = HeatBalanceIntRadExchange::GetRadiantSystemSurface(
     585          12 :                 state, cCMO_CoolingPanel_Simple, ThisCP.EquipID, ThisCP.ZonePtr, ThisCP.SurfaceName(SurfNum), ErrorsFound);
     586          12 :             ThisCP.FracDistribToSurf(SurfNum) = state.dataIPShortCut->rNumericArgs(SurfNum + 11);
     587          12 :             if (ThisCP.FracDistribToSurf(SurfNum) > MaxFraction) {
     588           0 :                 ShowWarningError(state,
     589           0 :                                  std::string{RoutineName} + cCMO_CoolingPanel_Simple + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", " +
     590           0 :                                      state.dataIPShortCut->cNumericFieldNames(SurfNum + 8) + "was greater than the allowable maximum.");
     591           0 :                 ShowContinueError(state, format("...reset to maximum value=[{:.2R}].", MaxFraction));
     592           0 :                 ThisCP.TotSurfToDistrib = MaxFraction;
     593             :             }
     594          12 :             if (ThisCP.FracDistribToSurf(SurfNum) < MinFraction) {
     595           0 :                 ShowWarningError(state,
     596           0 :                                  std::string{RoutineName} + cCMO_CoolingPanel_Simple + "=\"" + state.dataIPShortCut->cAlphaArgs(1) + "\", " +
     597           0 :                                      state.dataIPShortCut->cNumericFieldNames(SurfNum + 8) + "was less than the allowable minimum.");
     598           0 :                 ShowContinueError(state, format("...reset to maximum value=[{:.2R}].", MinFraction));
     599           0 :                 ThisCP.TotSurfToDistrib = MinFraction;
     600             :             }
     601          12 :             if (ThisCP.SurfacePtr(SurfNum) != 0) {
     602          12 :                 state.dataSurface->SurfIntConvSurfGetsRadiantHeat(ThisCP.SurfacePtr(SurfNum)) = true;
     603             :             }
     604             : 
     605          12 :             AllFracsSummed += ThisCP.FracDistribToSurf(SurfNum);
     606             :         } // Surfaces
     607             : 
     608           4 :         if (AllFracsSummed > (MaxFraction + 0.01)) {
     609           0 :             ShowSevereError(state,
     610           0 :                             std::string{RoutineName} + cCMO_CoolingPanel_Simple + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
     611             :                                 "\", Summed radiant fractions for people + surface groups > 1.0");
     612           0 :             ErrorsFound = true;
     613             :         }
     614           4 :         if ((AllFracsSummed < (MaxFraction - 0.01)) &&
     615           0 :             (ThisCP.FracRadiant > MinFraction)) { // User didn't distribute all of the | radiation warn that some will be lost
     616           0 :             ShowSevereError(state,
     617           0 :                             std::string{RoutineName} + cCMO_CoolingPanel_Simple + "=\"" + state.dataIPShortCut->cAlphaArgs(1) +
     618             :                                 "\", Summed radiant fractions for people + surface groups < 1.0");
     619           0 :             ShowContinueError(state, "This would result in some of the radiant energy delivered by the high temp radiant heater being lost.");
     620           0 :             ShowContinueError(state, format("The sum of all radiation fractions to surfaces = {:.5T}", (AllFracsSummed - ThisCP.FracDistribPerson)));
     621           0 :             ShowContinueError(state, format("The radiant fraction to people = {:.5T}", ThisCP.FracDistribPerson));
     622           0 :             ShowContinueError(state, format("So, all radiant fractions including surfaces and people = {:.5T}", AllFracsSummed));
     623           0 :             ShowContinueError(state,
     624           0 :                               format("This means that the fraction of radiant energy that would be lost from the high temperature radiant heater "
     625             :                                      "would be = {:.5T}",
     626           0 :                                      (1.0 - AllFracsSummed)));
     627           0 :             ShowContinueError(state,
     628           0 :                               "Please check and correct this so that all radiant energy is accounted for in " + cCMO_CoolingPanel_Simple + " = " +
     629           0 :                                   state.dataIPShortCut->cAlphaArgs(1));
     630           0 :             ErrorsFound = true;
     631             :         }
     632             :     }
     633             : 
     634           4 :     if (ErrorsFound) {
     635           0 :         ShowFatalError(state, std::string{RoutineName} + cCMO_CoolingPanel_Simple + "Errors found getting input. Program terminates.");
     636             :     }
     637             : 
     638             :     // Setup Report variables for the Coils
     639           8 :     for (CoolingPanelNum = 1; CoolingPanelNum <= NumCoolingPanels; ++CoolingPanelNum) {
     640             :         // CurrentModuleObject='ZoneHVAC:CoolingPanel:RadiantConvective:Water'
     641          16 :         SetupOutputVariable(state,
     642             :                             "Cooling Panel Total Cooling Rate",
     643             :                             OutputProcessor::Unit::W,
     644           4 :                             state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum).Power,
     645             :                             OutputProcessor::SOVTimeStepType::System,
     646             :                             OutputProcessor::SOVStoreType::Average,
     647           8 :                             state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum).EquipID);
     648          16 :         SetupOutputVariable(state,
     649             :                             "Cooling Panel Total System Cooling Rate",
     650             :                             OutputProcessor::Unit::W,
     651           4 :                             state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum).TotPower,
     652             :                             OutputProcessor::SOVTimeStepType::System,
     653             :                             OutputProcessor::SOVStoreType::Average,
     654           8 :                             state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum).EquipID);
     655          16 :         SetupOutputVariable(state,
     656             :                             "Cooling Panel Convective Cooling Rate",
     657             :                             OutputProcessor::Unit::W,
     658           4 :                             state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum).ConvPower,
     659             :                             OutputProcessor::SOVTimeStepType::System,
     660             :                             OutputProcessor::SOVStoreType::Average,
     661           8 :                             state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum).EquipID);
     662          16 :         SetupOutputVariable(state,
     663             :                             "Cooling Panel Radiant Cooling Rate",
     664             :                             OutputProcessor::Unit::W,
     665           4 :                             state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum).RadPower,
     666             :                             OutputProcessor::SOVTimeStepType::System,
     667             :                             OutputProcessor::SOVStoreType::Average,
     668           8 :                             state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum).EquipID);
     669             : 
     670          16 :         SetupOutputVariable(state,
     671             :                             "Cooling Panel Total Cooling Energy",
     672             :                             OutputProcessor::Unit::J,
     673           4 :                             state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum).Energy,
     674             :                             OutputProcessor::SOVTimeStepType::System,
     675             :                             OutputProcessor::SOVStoreType::Summed,
     676           4 :                             state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum).EquipID,
     677             :                             _,
     678             :                             "ENERGYTRANSFER",
     679             :                             "COOLINGPANEL",
     680             :                             _,
     681           4 :                             "System");
     682          16 :         SetupOutputVariable(state,
     683             :                             "Cooling Panel Total System Cooling Energy",
     684             :                             OutputProcessor::Unit::J,
     685           4 :                             state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum).TotEnergy,
     686             :                             OutputProcessor::SOVTimeStepType::System,
     687             :                             OutputProcessor::SOVStoreType::Summed,
     688           4 :                             state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum).EquipID,
     689             :                             _,
     690             :                             "ENERGYTRANSFER",
     691             :                             "COOLINGPANEL",
     692             :                             _,
     693           4 :                             "System");
     694          16 :         SetupOutputVariable(state,
     695             :                             "Cooling Panel Convective Cooling Energy",
     696             :                             OutputProcessor::Unit::J,
     697           4 :                             state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum).ConvEnergy,
     698             :                             OutputProcessor::SOVTimeStepType::System,
     699             :                             OutputProcessor::SOVStoreType::Summed,
     700           8 :                             state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum).EquipID);
     701          16 :         SetupOutputVariable(state,
     702             :                             "Cooling Panel Radiant Cooling Energy",
     703             :                             OutputProcessor::Unit::J,
     704           4 :                             state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum).RadEnergy,
     705             :                             OutputProcessor::SOVTimeStepType::System,
     706             :                             OutputProcessor::SOVStoreType::Summed,
     707           8 :                             state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum).EquipID);
     708             : 
     709          16 :         SetupOutputVariable(state,
     710             :                             "Cooling Panel Water Mass Flow Rate",
     711             :                             OutputProcessor::Unit::kg_s,
     712           4 :                             state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum).WaterMassFlowRate,
     713             :                             OutputProcessor::SOVTimeStepType::System,
     714             :                             OutputProcessor::SOVStoreType::Average,
     715           8 :                             state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum).EquipID);
     716          16 :         SetupOutputVariable(state,
     717             :                             "Cooling Panel Water Inlet Temperature",
     718             :                             OutputProcessor::Unit::C,
     719           4 :                             state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum).WaterInletTemp,
     720             :                             OutputProcessor::SOVTimeStepType::System,
     721             :                             OutputProcessor::SOVStoreType::Average,
     722           8 :                             state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum).EquipID);
     723          16 :         SetupOutputVariable(state,
     724             :                             "Cooling Panel Water Outlet Temperature",
     725             :                             OutputProcessor::Unit::C,
     726           4 :                             state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum).WaterOutletTemp,
     727             :                             OutputProcessor::SOVTimeStepType::System,
     728             :                             OutputProcessor::SOVStoreType::Average,
     729           8 :                             state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum).EquipID);
     730             :     }
     731           4 : }
     732             : 
     733       22551 : void InitCoolingPanel(EnergyPlusData &state, int const CoolingPanelNum, int const ControlledZoneNum, bool const FirstHVACIteration)
     734             : {
     735             : 
     736             :     // SUBROUTINE INFORMATION:
     737             :     //       AUTHOR         Rick Strand
     738             :     //       DATE WRITTEN   Sept 2014
     739             : 
     740             :     // PURPOSE OF THIS SUBROUTINE:
     741             :     // This subroutine initializes the cooling panel units, and determines the UA values during simulation.
     742             : 
     743             :     // METHODOLOGY EMPLOYED:
     744             :     // The initialization subrotines borrowed from other sources and heat exchanger formulation for cooling panel.
     745             : 
     746             :     // REFERENCES:
     747             :     // Incropera and DeWitt, Fundamentals of Heat and Mass Transfer
     748             : 
     749             :     // Using/Aliasing
     750             :     using DataZoneEquipment::CheckZoneEquipmentList;
     751             :     using FluidProperties::GetDensityGlycol;
     752             :     using FluidProperties::GetSpecificHeatGlycol;
     753             :     using PlantUtilities::InitComponentNodes;
     754             :     using PlantUtilities::ScanPlantLoopsForObject;
     755             : 
     756             :     // SUBROUTINE PARAMETER DEFINITIONS:
     757             :     static constexpr std::string_view RoutineName("ChilledCeilingPanelSimple:InitCoolingPanel");
     758             : 
     759             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     760             :     Real64 rho; // local fluid density
     761             :     Real64 Cp;  // local fluid specific heat
     762             :     bool errFlag;
     763             : 
     764       22551 :     auto &ThisCP(state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum));
     765       22551 :     auto &ThisInNode(state.dataLoopNodes->Node(ThisCP.WaterInletNode));
     766             : 
     767       22551 :     if (ThisCP.ZonePtr <= 0) ThisCP.ZonePtr = ControlledZoneNum;
     768             : 
     769             :     // Need to check all units to see if they are on ZoneHVAC:EquipmentList or issue warning
     770       22551 :     if (!ThisCP.ZoneEquipmentListChecked && state.dataZoneEquip->ZoneEquipInputsFilled) {
     771           4 :         ThisCP.ZoneEquipmentListChecked = true;
     772           4 :         if (!CheckZoneEquipmentList(state, cCMO_CoolingPanel_Simple, ThisCP.EquipID)) {
     773           0 :             ShowSevereError(state,
     774           0 :                             "InitCoolingPanel: Unit=[" + cCMO_CoolingPanel_Simple + ',' + ThisCP.EquipID +
     775             :                                 "] is not on any ZoneHVAC:EquipmentList.  It will not be simulated.");
     776             :         }
     777             :     }
     778             : 
     779       22551 :     if (ThisCP.SetLoopIndexFlag) {
     780           4 :         if (allocated(state.dataPlnt->PlantLoop)) {
     781           4 :             errFlag = false;
     782           4 :             ScanPlantLoopsForObject(state, ThisCP.EquipID, ThisCP.EquipType, ThisCP.plantLoc, errFlag, _, _, _, _, _);
     783           4 :             if (errFlag) {
     784           0 :                 ShowFatalError(state, "InitCoolingPanel: Program terminated for previous conditions.");
     785             :             }
     786           4 :             ThisCP.SetLoopIndexFlag = false;
     787             :         }
     788             :     }
     789             : 
     790       22551 :     if (!state.dataGlobal->SysSizingCalc) {
     791       22547 :         if (ThisCP.MySizeFlagCoolPanel && !ThisCP.SetLoopIndexFlag) {
     792             :             // for each cooling panel do the sizing once.
     793           4 :             SizeCoolingPanel(state, CoolingPanelNum);
     794           4 :             ThisCP.MySizeFlagCoolPanel = false;
     795             : 
     796             :             // set design mass flow rates
     797           4 :             if (ThisCP.WaterInletNode > 0) {
     798           8 :                 rho = GetDensityGlycol(state,
     799           4 :                                        state.dataPlnt->PlantLoop(ThisCP.plantLoc.loopNum).FluidName,
     800             :                                        DataGlobalConstants::CWInitConvTemp,
     801           4 :                                        state.dataPlnt->PlantLoop(ThisCP.plantLoc.loopNum).FluidIndex,
     802             :                                        RoutineName);
     803           4 :                 ThisCP.WaterMassFlowRateMax = rho * ThisCP.WaterVolFlowRateMax;
     804           4 :                 InitComponentNodes(state, 0.0, ThisCP.WaterMassFlowRateMax, ThisCP.WaterInletNode, ThisCP.WaterOutletNode);
     805             :             }
     806             :         }
     807             :     }
     808             : 
     809             :     // Do the Begin Environment initializations
     810       22551 :     if (state.dataGlobal->BeginEnvrnFlag && ThisCP.MyEnvrnFlag) {
     811             :         // Initialize
     812             : 
     813          48 :         rho = GetDensityGlycol(state,
     814          24 :                                state.dataPlnt->PlantLoop(ThisCP.plantLoc.loopNum).FluidName,
     815             :                                DataGlobalConstants::InitConvTemp,
     816          24 :                                state.dataPlnt->PlantLoop(ThisCP.plantLoc.loopNum).FluidIndex,
     817             :                                RoutineName);
     818             : 
     819          24 :         ThisCP.WaterMassFlowRateMax = rho * ThisCP.WaterVolFlowRateMax;
     820             : 
     821          24 :         InitComponentNodes(state, 0.0, ThisCP.WaterMassFlowRateMax, ThisCP.WaterInletNode, ThisCP.WaterOutletNode);
     822             : 
     823          24 :         ThisInNode.Temp = 7.0;
     824             : 
     825          48 :         Cp = GetSpecificHeatGlycol(state,
     826          24 :                                    state.dataPlnt->PlantLoop(ThisCP.plantLoc.loopNum).FluidName,
     827             :                                    ThisInNode.Temp,
     828          24 :                                    state.dataPlnt->PlantLoop(ThisCP.plantLoc.loopNum).FluidIndex,
     829             :                                    RoutineName);
     830             : 
     831          24 :         ThisInNode.Enthalpy = Cp * ThisInNode.Temp;
     832          24 :         ThisInNode.Quality = 0.0;
     833          24 :         ThisInNode.Press = 0.0;
     834          24 :         ThisInNode.HumRat = 0.0;
     835             : 
     836          24 :         ThisCP.ZeroSourceSumHATsurf = 0.0;
     837          24 :         ThisCP.CoolingPanelSource = 0.0;
     838          24 :         ThisCP.CoolingPanelSrcAvg = 0.0;
     839          24 :         ThisCP.LastCoolingPanelSrc = 0.0;
     840          24 :         ThisCP.LastSysTimeElapsed = 0.0;
     841          24 :         ThisCP.LastTimeStepSys = 0.0;
     842             : 
     843          24 :         ThisCP.MyEnvrnFlag = false;
     844             :     }
     845             : 
     846       22551 :     if (!state.dataGlobal->BeginEnvrnFlag) {
     847       22421 :         ThisCP.MyEnvrnFlag = true;
     848             :     }
     849             : 
     850       22551 :     if (state.dataGlobal->BeginTimeStepFlag && FirstHVACIteration) {
     851        8108 :         int ZoneNum = ThisCP.ZonePtr;
     852        8108 :         state.dataHeatBal->Zone(ZoneNum).ZeroSourceSumHATsurf = state.dataHeatBal->Zone(ZoneNum).sumHATsurf(state);
     853        8108 :         ThisCP.CoolingPanelSrcAvg = 0.0;
     854        8108 :         ThisCP.LastCoolingPanelSrc = 0.0;
     855        8108 :         ThisCP.LastSysTimeElapsed = 0.0;
     856        8108 :         ThisCP.LastTimeStepSys = 0.0;
     857             :     }
     858             : 
     859             :     // Do the every time step initializations
     860       22551 :     ThisCP.WaterMassFlowRate = ThisInNode.MassFlowRate;
     861       22551 :     ThisCP.WaterInletTemp = ThisInNode.Temp;
     862       22551 :     ThisCP.WaterInletEnthalpy = ThisInNode.Enthalpy;
     863       22551 :     ThisCP.TotPower = 0.0;
     864       22551 :     ThisCP.Power = 0.0;
     865       22551 :     ThisCP.ConvPower = 0.0;
     866       22551 :     ThisCP.RadPower = 0.0;
     867       22551 :     ThisCP.TotEnergy = 0.0;
     868       22551 :     ThisCP.Energy = 0.0;
     869       22551 :     ThisCP.ConvEnergy = 0.0;
     870       22551 :     ThisCP.RadEnergy = 0.0;
     871       22551 : }
     872             : 
     873           4 : void SizeCoolingPanel(EnergyPlusData &state, int const CoolingPanelNum)
     874             : {
     875             :     // SUBROUTINE INFORMATION:
     876             :     //       AUTHOR         Rick Strand
     877             :     //       DATE WRITTEN   Sept 2016
     878             : 
     879             :     // PURPOSE OF THIS SUBROUTINE:
     880             :     // This subroutine sizes the simple chilled ceiling panel.  The process used here
     881             :     // was derived from the low temperature radiant system model and adapted for
     882             :     // cooling only.
     883             : 
     884             :     using DataHVACGlobals::AutoCalculateSizing;
     885             :     using DataHVACGlobals::CoolingCapacitySizing;
     886             :     using DataHVACGlobals::SmallLoad;
     887             :     using DataSizing::AutoSize;
     888             :     using DataSizing::CapacityPerFloorArea;
     889             :     using DataSizing::CoolingDesignCapacity;
     890             :     using DataSizing::FractionOfAutosizedCoolingCapacity;
     891             :     using FluidProperties::GetDensityGlycol;
     892             :     using FluidProperties::GetSpecificHeatGlycol;
     893             :     using PlantUtilities::MyPlantSizingIndex;
     894             :     using PlantUtilities::RegisterPlantCompDesignFlow;
     895             : 
     896             :     // SUBROUTINE PARAMETER DEFINITIONS:
     897             :     static constexpr std::string_view RoutineName("SizeCoolingPanel");
     898             : 
     899             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
     900           4 :     bool ErrorsFound(false);  // If errors detected in input
     901           8 :     std::string CompName;     // component name
     902           8 :     std::string CompType;     // component type
     903           4 :     bool IsAutoSize(false);   // Indicator to autosize
     904             :     Real64 DesCoilLoad;       // design autosized or user specified capacity
     905             :     int SizingMethod;         // Integer representation of sizing method name (e.g. CoolingCapacitySizing, HeatingCapacitySizing)
     906           4 :     int FieldNum = 1;         // IDD numeric field number where input field description is found
     907             :     bool PrintFlag;           // TRUE when sizing information is reported in the eio file
     908           8 :     std::string SizingString; // input field sizing description (e.g., Nominal Capacity)
     909             :     Real64 TempSize;          // autosized value of coil input field
     910           4 :     int CapSizingMethod(0);   // capacity sizing methods (HeatingDesignCapacity, CapacityPerFloorArea, FractionOfAutosizedCoolingCapacity, and
     911             :                               // FractionOfAutosizedHeatingCapacity )
     912           4 :     int PltSizCoolNum(0);     // index of plant sizing object for 1st cooling loop
     913             :     Real64 rho;
     914             :     Real64 Cp;
     915           4 :     Real64 WaterVolFlowMaxCoolDes(0.0);  // Design chilled water flow for reporting
     916           4 :     Real64 WaterVolFlowMaxCoolUser(0.0); // User hard-sized chilled water flow for reporting
     917             : 
     918           4 :     DesCoilLoad = 0.0;
     919           4 :     state.dataSize->DataScalableCapSizingON = false;
     920             : 
     921           4 :     auto &ThisCP(state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum));
     922           4 :     auto &ZoneEqSizing(state.dataSize->ZoneEqSizing);
     923             : 
     924           4 :     CompType = "ZoneHVAC:CoolingPanel:RadiantConvective:Water";
     925           4 :     CompName = ThisCP.EquipID;
     926             : 
     927           4 :     IsAutoSize = false;
     928           4 :     if (ThisCP.ScaledCoolingCapacity == AutoSize) {
     929           1 :         IsAutoSize = true;
     930             :     }
     931             : 
     932           4 :     if (state.dataSize->CurZoneEqNum > 0) {
     933             : 
     934           4 :         SizingMethod = CoolingCapacitySizing;
     935           4 :         FieldNum = 4;
     936           4 :         PrintFlag = true;
     937           4 :         bool errorsFound = false;
     938           4 :         SizingString = ThisCP.FieldNames(FieldNum) + " [W]";
     939           4 :         CapSizingMethod = ThisCP.CoolingCapMethod;
     940           4 :         ZoneEqSizing(state.dataSize->CurZoneEqNum).SizingMethod(SizingMethod) = CapSizingMethod;
     941             : 
     942           4 :         if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) { // simulation continue
     943           0 :             if (CapSizingMethod == CoolingDesignCapacity && ThisCP.ScaledCoolingCapacity > 0.0) {
     944           0 :                 TempSize = ThisCP.ScaledCoolingCapacity;
     945           0 :                 CoolingCapacitySizer sizerCoolingCapacity;
     946           0 :                 sizerCoolingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
     947           0 :                 DesCoilLoad = sizerCoolingCapacity.size(state, TempSize, errorsFound);
     948           0 :             } else if (CapSizingMethod == CapacityPerFloorArea) {
     949           0 :                 state.dataSize->DataScalableCapSizingON = true;
     950           0 :                 TempSize = ThisCP.ScaledCoolingCapacity * state.dataHeatBal->Zone(ThisCP.ZonePtr).FloorArea;
     951           0 :                 CoolingCapacitySizer sizerCoolingCapacity;
     952           0 :                 sizerCoolingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
     953           0 :                 DesCoilLoad = sizerCoolingCapacity.size(state, TempSize, errorsFound);
     954           0 :                 state.dataSize->DataScalableCapSizingON = false;
     955           0 :             } else if (CapSizingMethod == FractionOfAutosizedCoolingCapacity) {
     956           0 :                 if (ThisCP.WaterVolFlowRateMax == AutoSize) {
     957           0 :                     ShowSevereError(state,
     958           0 :                                     std::string{RoutineName} + ": auto-sizing cannot be done for " + CompType + " = " + ThisCP.EquipID + "\".");
     959           0 :                     ShowContinueError(state,
     960             :                                       "The \"SimulationControl\" object must have the field \"Do Zone Sizing Calculation\" set to Yes when the "
     961             :                                       "Cooling Design Capacity Method = \"FractionOfAutosizedCoolingCapacity\".");
     962           0 :                     ErrorsFound = true;
     963             :                 }
     964             :             }
     965             :         } else { // Autosize or hard-size with sizing run
     966           4 :             if (CapSizingMethod == CoolingDesignCapacity || CapSizingMethod == CapacityPerFloorArea ||
     967             :                 CapSizingMethod == FractionOfAutosizedCoolingCapacity) {
     968           4 :                 if (CapSizingMethod == CoolingDesignCapacity) {
     969           2 :                     if (state.dataSize->ZoneSizingRunDone) {
     970           2 :                         CheckZoneSizing(state, CompType, CompName);
     971           2 :                         SizingMethod = AutoCalculateSizing;
     972           2 :                         state.dataSize->DataConstantUsedForSizing =
     973           2 :                             state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).NonAirSysDesCoolLoad;
     974           2 :                         state.dataSize->DataFractionUsedForSizing = 1.0;
     975             :                     }
     976           2 :                     if (ThisCP.ScaledCoolingCapacity == AutoSize) {
     977           1 :                         TempSize = AutoSize;
     978             :                     } else {
     979           1 :                         TempSize = ThisCP.ScaledCoolingCapacity;
     980             :                     }
     981           2 :                 } else if (CapSizingMethod == CapacityPerFloorArea) {
     982           1 :                     if (state.dataSize->ZoneSizingRunDone) {
     983           1 :                         CheckZoneSizing(state, CompType, CompName);
     984           1 :                         ZoneEqSizing(state.dataSize->CurZoneEqNum).CoolingCapacity = true;
     985           1 :                         ZoneEqSizing(state.dataSize->CurZoneEqNum).DesCoolingLoad =
     986           1 :                             state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).NonAirSysDesCoolLoad;
     987             :                     }
     988           1 :                     TempSize = ThisCP.ScaledCoolingCapacity * state.dataHeatBal->Zone(ThisCP.ZonePtr).FloorArea;
     989           1 :                     state.dataSize->DataScalableCapSizingON = true;
     990           1 :                 } else if (CapSizingMethod == FractionOfAutosizedCoolingCapacity) {
     991           1 :                     CheckZoneSizing(state, CompType, CompName);
     992           1 :                     ZoneEqSizing(state.dataSize->CurZoneEqNum).CoolingCapacity = true;
     993           1 :                     ZoneEqSizing(state.dataSize->CurZoneEqNum).DesCoolingLoad =
     994           1 :                         state.dataSize->FinalZoneSizing(state.dataSize->CurZoneEqNum).NonAirSysDesCoolLoad;
     995           1 :                     TempSize = ZoneEqSizing(state.dataSize->CurZoneEqNum).DesCoolingLoad * ThisCP.ScaledCoolingCapacity;
     996           1 :                     state.dataSize->DataScalableCapSizingON = true;
     997             : 
     998             :                 } else {
     999           0 :                     TempSize = ThisCP.ScaledCoolingCapacity;
    1000             :                 }
    1001           8 :                 CoolingCapacitySizer sizerCoolingCapacity;
    1002           4 :                 sizerCoolingCapacity.initializeWithinEP(state, CompType, CompName, PrintFlag, RoutineName);
    1003           4 :                 DesCoilLoad = sizerCoolingCapacity.size(state, TempSize, errorsFound);
    1004           4 :                 state.dataSize->DataConstantUsedForSizing = 0.0;
    1005           4 :                 state.dataSize->DataFractionUsedForSizing = 0.0;
    1006           8 :                 state.dataSize->DataScalableCapSizingON = false;
    1007             :             } else {
    1008           0 :                 DesCoilLoad = 0.0;
    1009             :             }
    1010             :         }
    1011             :         // finally cooling capacity is saved in this variable
    1012           4 :         ThisCP.ScaledCoolingCapacity = DesCoilLoad;
    1013             :     }
    1014             : 
    1015           4 :     IsAutoSize = false;
    1016           4 :     if (ThisCP.WaterVolFlowRateMax == AutoSize) {
    1017           1 :         IsAutoSize = true;
    1018             :     }
    1019           4 :     if (state.dataSize->CurZoneEqNum > 0) {
    1020           4 :         if (!IsAutoSize && !state.dataSize->ZoneSizingRunDone) { // simulation continue
    1021           0 :             if (ThisCP.WaterVolFlowRateMax > 0.0) {
    1022           0 :                 BaseSizer::reportSizerOutput(
    1023           0 :                     state, CompType, ThisCP.EquipID, "User-Specified Maximum Cold Water Flow [m3/s]", ThisCP.WaterVolFlowRateMax);
    1024             :             }
    1025             :         } else { // Autosize or hard-size with sizing run
    1026           4 :             if (ThisCP.WaterInletNode > 0 && ThisCP.WaterOutletNode > 0) {
    1027           4 :                 PltSizCoolNum = MyPlantSizingIndex(state, CompType, ThisCP.EquipID, ThisCP.WaterInletNode, ThisCP.WaterOutletNode, ErrorsFound);
    1028           4 :                 if (PltSizCoolNum > 0) {
    1029           4 :                     if (DesCoilLoad >= SmallLoad) {
    1030           8 :                         rho = GetDensityGlycol(state,
    1031           4 :                                                state.dataPlnt->PlantLoop(ThisCP.plantLoc.loopNum).FluidName,
    1032             :                                                5.,
    1033           4 :                                                state.dataPlnt->PlantLoop(ThisCP.plantLoc.loopNum).FluidIndex,
    1034             :                                                RoutineName);
    1035           8 :                         Cp = GetSpecificHeatGlycol(state,
    1036           4 :                                                    state.dataPlnt->PlantLoop(ThisCP.plantLoc.loopNum).FluidName,
    1037             :                                                    5.0,
    1038           4 :                                                    state.dataPlnt->PlantLoop(ThisCP.plantLoc.loopNum).FluidIndex,
    1039             :                                                    RoutineName);
    1040           4 :                         WaterVolFlowMaxCoolDes = DesCoilLoad / (state.dataSize->PlantSizData(PltSizCoolNum).DeltaT * Cp * rho);
    1041             :                     } else {
    1042           0 :                         WaterVolFlowMaxCoolDes = 0.0;
    1043             :                     }
    1044             :                 } else {
    1045           0 :                     ShowSevereError(state, "Autosizing of water flow requires a cooling loop Sizing:Plant object");
    1046           0 :                     ShowContinueError(state, "Occurs in ZoneHVAC:CoolingPanel:RadiantConvective:Water Object=" + ThisCP.EquipID);
    1047           0 :                     ErrorsFound = true;
    1048             :                 }
    1049             :             }
    1050             : 
    1051           4 :             if (IsAutoSize) {
    1052           1 :                 ThisCP.WaterVolFlowRateMax = WaterVolFlowMaxCoolDes;
    1053           1 :                 BaseSizer::reportSizerOutput(state, CompType, ThisCP.EquipID, "Design Size Maximum Cold Water Flow [m3/s]", WaterVolFlowMaxCoolDes);
    1054             :             } else { // hard-size with sizing data
    1055           3 :                 if (ThisCP.WaterVolFlowRateMax > 0.0 && WaterVolFlowMaxCoolDes > 0.0) {
    1056           3 :                     WaterVolFlowMaxCoolUser = ThisCP.WaterVolFlowRateMax;
    1057           6 :                     BaseSizer::reportSizerOutput(state,
    1058             :                                                  CompType,
    1059             :                                                  ThisCP.EquipID,
    1060             :                                                  "Design Size Maximum Cold Water Flow [m3/s]",
    1061             :                                                  WaterVolFlowMaxCoolDes,
    1062             :                                                  "User-Specified Maximum Cold Water Flow [m3/s]",
    1063           3 :                                                  WaterVolFlowMaxCoolUser);
    1064           3 :                     if (state.dataGlobal->DisplayExtraWarnings) {
    1065           0 :                         if ((std::abs(WaterVolFlowMaxCoolDes - WaterVolFlowMaxCoolUser) / WaterVolFlowMaxCoolUser) >
    1066           0 :                             state.dataSize->AutoVsHardSizingThreshold) {
    1067           0 :                             ShowMessage(
    1068             :                                 state,
    1069           0 :                                 "SizeCoolingPanel: Potential issue with equipment sizing for ZoneHVAC:CoolingPanel:RadiantConvective:Water = \"" +
    1070           0 :                                     ThisCP.EquipID + "\".");
    1071           0 :                             ShowContinueError(state, format("User-Specified Maximum Cool Water Flow of {:.5R} [m3/s]", WaterVolFlowMaxCoolUser));
    1072           0 :                             ShowContinueError(state,
    1073           0 :                                               format("differs from Design Size Maximum Cool Water Flow of {:.5R} [m3/s]", WaterVolFlowMaxCoolDes));
    1074           0 :                             ShowContinueError(state, "This may, or may not, indicate mismatched component sizes.");
    1075           0 :                             ShowContinueError(state, "Verify that the value entered is intended and is consistent with other components.");
    1076             :                         }
    1077             :                     }
    1078             :                 }
    1079             :             }
    1080             :         }
    1081             :     }
    1082             : 
    1083           4 :     RegisterPlantCompDesignFlow(state, ThisCP.WaterInletNode, ThisCP.WaterVolFlowRateMax);
    1084             : 
    1085             :     bool SizeCoolingPanelUASuccess;
    1086           4 :     SizeCoolingPanelUASuccess = ThisCP.SizeCoolingPanelUA(state);
    1087           4 :     if (!SizeCoolingPanelUASuccess) ShowFatalError(state, "SizeCoolingPanelUA: Program terminated for previous conditions.");
    1088           4 : }
    1089             : 
    1090           4 : bool CoolingPanelParams::SizeCoolingPanelUA(EnergyPlusData &state)
    1091             : {
    1092             : 
    1093             :     // SUBROUTINE INFORMATION:
    1094             :     //       AUTHOR         Rick Strand
    1095             :     //       DATE WRITTEN   June 2017
    1096             : 
    1097             :     // PURPOSE OF THIS SUBROUTINE:
    1098             :     // This subroutine sizes UA value for the simple chilled ceiling panel.
    1099             : 
    1100             :     // Return value
    1101             :     bool SizeCoolingPanelUA;
    1102             : 
    1103             :     // These initializations are mainly the calculation of the UA value for the heat exchanger formulation of the simple cooling panel
    1104             :     Real64 Cp;
    1105             :     Real64 MDot;
    1106             :     Real64 MDotXCp;
    1107             :     Real64 Qrated;
    1108             :     Real64 Tinletr;
    1109             :     Real64 Tzoner;
    1110             :     Real64 RatCapToTheoMax; // Ratio of unit capacity to theoretical maximum output based on rated parameters
    1111             : 
    1112           4 :     SizeCoolingPanelUA = true;
    1113           4 :     Cp = 4120.0; // Just an approximation, don't need to get an exact number
    1114           4 :     MDot = this->RatedWaterFlowRate;
    1115           4 :     MDotXCp = Cp * MDot;
    1116           4 :     Qrated = this->ScaledCoolingCapacity;
    1117           4 :     Tinletr = this->RatedWaterTemp;
    1118           4 :     Tzoner = this->RatedZoneAirTemp;
    1119           4 :     if (std::abs(Tinletr - Tzoner) < 0.5) {
    1120           0 :         RatCapToTheoMax = std::abs(Qrated) / (MDotXCp * 0.5); // Avoid a divide by zero error
    1121             :     } else {
    1122           4 :         RatCapToTheoMax = std::abs(Qrated) / (MDotXCp * std::abs(Tinletr - Tzoner));
    1123             :     }
    1124           4 :     if ((RatCapToTheoMax < 1.1) && (RatCapToTheoMax > 0.9999)) {
    1125             :         // close to unity with some graciousness given in case the approximation of Cp causes a problem
    1126           0 :         RatCapToTheoMax = 0.9999;
    1127           4 :     } else if (RatCapToTheoMax >= 1.1) {
    1128           0 :         ShowSevereError(state,
    1129           0 :                         "SizeCoolingPanelUA: Unit=[" + cCMO_CoolingPanel_Simple + ',' + this->EquipID +
    1130             :                             "] has a cooling capacity that is greater than the maximum possible value.");
    1131           0 :         ShowContinueError(state, "The result of this is that a UA value is impossible to calculate.");
    1132           0 :         ShowContinueError(state, "Check the rated input for temperatures, flow, and capacity for this unit.");
    1133           0 :         ShowContinueError(state, "The ratio of the capacity to the rated theoretical maximum must be less than unity.");
    1134           0 :         ShowContinueError(state,
    1135             :                           "The most likely cause for this is probably either the capacity (whether autosized or hardwired) being too high, the "
    1136             :                           "rated flow being too low, rated temperatures being too close to each other, or all of those reasons.");
    1137           0 :         ShowContinueError(state,
    1138             :                           "Compare the rated capacity in your input to the product of the rated mass flow rate, Cp of water, and the difference "
    1139             :                           "between the rated temperatures.");
    1140           0 :         ShowContinueError(
    1141             :             state, "If the rated capacity is higher than this product, then the cooling panel would violate the Second Law of Thermodynamics.");
    1142           0 :         SizeCoolingPanelUA = false;
    1143           0 :         this->UA = 1.0;
    1144             :     }
    1145           4 :     if (Tinletr >= Tzoner) {
    1146           0 :         ShowSevereError(state,
    1147           0 :                         "SizeCoolingPanelUA: Unit=[" + cCMO_CoolingPanel_Simple + ',' + this->EquipID +
    1148             :                             "] has a rated water temperature that is higher than the rated zone temperature.");
    1149           0 :         ShowContinueError(state,
    1150             :                           "Such a situation would not lead to cooling and thus the rated water or zone temperature or both should be adjusted.");
    1151           0 :         SizeCoolingPanelUA = false;
    1152           0 :         this->UA = 1.0;
    1153             :     } else {
    1154           4 :         this->UA = -MDotXCp * log(1.0 - RatCapToTheoMax);
    1155           4 :         if (this->UA <= 0.0) {
    1156           0 :             ShowSevereError(state,
    1157           0 :                             "SizeCoolingPanelUA: Unit=[" + cCMO_CoolingPanel_Simple + ',' + this->EquipID +
    1158             :                                 "] has a zero or negative calculated UA value.");
    1159           0 :             ShowContinueError(state,
    1160             :                               "This is not allowed.  Please check the rated input parameters for this device to ensure that the values are correct.");
    1161           0 :             SizeCoolingPanelUA = false;
    1162             :         }
    1163             :     }
    1164             : 
    1165           4 :     return SizeCoolingPanelUA;
    1166             : }
    1167             : 
    1168       22551 : void CoolingPanelParams::CalcCoolingPanel(EnergyPlusData &state, int const CoolingPanelNum)
    1169             : {
    1170             :     // SUBROUTINE INFORMATION:
    1171             :     //       AUTHOR         Rick Strand
    1172             :     //       DATE WRITTEN   Sept 2014
    1173             : 
    1174             :     // PURPOSE OF THIS SUBROUTINE:
    1175             :     // This subroutine calculates both the convective and radiant heat transfer rate
    1176             :     // for the simple cooling panel.  The process used here was derived from the hot
    1177             :     // water baseboard radiant/convective heater and adapted for cooling.
    1178             : 
    1179             :     // REFERENCES:
    1180             :     // Existing code for hot water baseboard models (radiant-convective variety)
    1181             :     // Incropera and DeWitt, Fundamentals of Heat and Mass Transfer
    1182             : 
    1183             :     // Using/Aliasing
    1184             :     using DataHVACGlobals::SmallLoad;
    1185             :     using FluidProperties::GetSpecificHeatGlycol;
    1186             : 
    1187             :     using PlantUtilities::SetComponentFlowRate;
    1188             :     using Psychrometrics::PsyTdpFnWPb;
    1189             :     using ScheduleManager::GetCurrentScheduleValue;
    1190             : 
    1191             :     // SUBROUTINE PARAMETER DEFINITIONS:
    1192       22551 :     Real64 constexpr MinFrac(0.0005); // Minimum fraction that delivers radiant heats to surfaces
    1193       22551 :     int constexpr Maxiter(20);        // Maximum number of iterations to achieve tolerance
    1194       22551 :     Real64 constexpr IterTol(0.005);  // Tolerance of 0.5%
    1195             :     static constexpr std::string_view RoutineName("CalcCoolingPanel");
    1196             : 
    1197             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1198             :     int ZoneNum;
    1199             :     int iter;
    1200             :     Real64 RadHeat;
    1201             :     Real64 CoolingPanelCool;
    1202             :     Real64 waterInletTemp;
    1203             :     Real64 waterOutletTemp;
    1204             :     Real64 waterMassFlowRate;
    1205             :     Real64 waterMassFlowRateMax;
    1206             :     Real64 CapacitanceWater;
    1207             :     Real64 NTU;
    1208             :     Real64 Effectiveness;
    1209             :     Real64 QZnReq;
    1210             :     Real64 Cp;
    1211             :     Real64 Tzone;
    1212             :     Real64 Xr;
    1213             :     Real64 MCpEpsAct;
    1214             :     Real64 MCpEpsLow;
    1215             :     Real64 MCpEpsHigh;
    1216             :     Real64 MdotLow;
    1217             :     Real64 MdotHigh;
    1218             :     Real64 FracGuess;
    1219             :     Real64 MdotGuess;
    1220             :     Real64 MCpEpsGuess;
    1221             :     Real64 ControlTemp;
    1222             :     Real64 SetPointTemp;
    1223             :     Real64 OffTempCool;
    1224             :     Real64 FullOnTempCool;
    1225             :     Real64 MassFlowFrac;
    1226             :     Real64 DewPointTemp;
    1227             :     Real64 LoadMet;
    1228             :     bool CoolingPanelOn;
    1229             :     bool ModifiedWaterInletTemp;
    1230             : 
    1231       22551 :     ModifiedWaterInletTemp = false;
    1232       22551 :     ZoneNum = this->ZonePtr;
    1233       22551 :     QZnReq = state.dataZoneEnergyDemand->ZoneSysEnergyDemand(ZoneNum).RemainingOutputReqToCoolSP;
    1234       22551 :     waterInletTemp = this->WaterInletTemp;
    1235       22551 :     waterOutletTemp = waterInletTemp;
    1236       22551 :     waterMassFlowRateMax = this->WaterMassFlowRateMax;
    1237       22551 :     Xr = this->FracRadiant;
    1238             : 
    1239       22551 :     if (GetCurrentScheduleValue(state, this->SchedPtr) > 0) {
    1240       22551 :         CoolingPanelOn = true;
    1241             :     } else {
    1242           0 :         CoolingPanelOn = false;
    1243             :     }
    1244             :     // Calculate the "zone" temperature for determining the output of the cooling panel
    1245       22551 :     Tzone = Xr * state.dataHeatBal->ZoneMRT(ZoneNum) + ((1.0 - Xr) * state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).MAT);
    1246             : 
    1247             :     // Logical controls: if the WaterInletTemperature is higher than Tzone, do not run the panel
    1248       22551 :     if (waterInletTemp >= Tzone) CoolingPanelOn = false;
    1249             : 
    1250             :     // Condensation Controls based on dewpoint temperature of the zone.
    1251             :     // The assumption here is that condensation might take place if the inlet water temperature
    1252             :     // is below the dewpoint temperature of the space.  This assumption is made because we are
    1253             :     // probably dealing with a metal panel and the surface temperature of the panel will be very
    1254             :     // close to the inlet water temperature in certain places.  Thus, if the water inlet temperature
    1255             :     // is below the dewpoint temperature, then we might have condensation.  We need to deal with this
    1256             :     // possibility based on the user selected method.  The good news here is that we don't have to
    1257             :     // iterate like in the low temperature radiant systems because the inlet water condition is known
    1258             :     // not calculated.  So, we can deal with this upfront rather than after calculation and then more
    1259             :     // iteration.
    1260       22551 :     DewPointTemp = PsyTdpFnWPb(state, state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).ZoneAirHumRat, state.dataEnvrn->OutBaroPress);
    1261             : 
    1262       22551 :     if (waterInletTemp < (DewPointTemp + this->CondDewPtDeltaT) && (CoolingPanelOn)) {
    1263             : 
    1264             :         // Condensation is possible so invoke the three possible ways of handling this based on the user's choice...
    1265             : 
    1266       11518 :         if (this->CondCtrlType == CondCtrl::NONE) {
    1267             :             // Condensation control is "off" which means don't do anything, simply let it run and ignore condensation
    1268        3386 :         } else if (this->CondCtrlType == CondCtrl::SIMPLEOFF) {
    1269             :             // For "simple off", simply turn the simple cooling panel off to avoid condensation
    1270           0 :             waterMassFlowRate = 0.0;
    1271           0 :             CoolingPanelOn = false;
    1272             :             // Produce a warning message so that user knows the system was shut-off due to potential for condensation
    1273           0 :             if (!state.dataGlobal->WarmupFlag) {
    1274           0 :                 if (this->CondErrIndex == 0) { // allow errors up to number of radiant systems
    1275           0 :                     ShowWarningMessage(state,
    1276           0 :                                        cCMO_CoolingPanel_Simple + " [" + this->EquipID +
    1277             :                                            "] inlet water temperature below dew-point temperature--potential for condensation exists");
    1278           0 :                     ShowContinueError(state, "Flow to the simple cooling panel will be shut-off to avoid condensation");
    1279           0 :                     ShowContinueError(state, format("Water inlet temperature = {:.2R}", waterInletTemp));
    1280           0 :                     ShowContinueError(state, format("Zone dew-point temperature + safety delta T= {:.2R}", DewPointTemp + this->CondDewPtDeltaT));
    1281           0 :                     ShowContinueErrorTimeStamp(state, "");
    1282           0 :                     ShowContinueError(state,
    1283           0 :                                       format("Note that a {:.4R} C safety was chosen in the input for the shut-off criteria", this->CondDewPtDeltaT));
    1284             :                 }
    1285           0 :                 ShowRecurringWarningErrorAtEnd(state,
    1286           0 :                                                cCMO_CoolingPanel_Simple + " [" + this->EquipID + "] condensation shut-off occurrence continues.",
    1287             :                                                this->CondErrIndex,
    1288             :                                                DewPointTemp,
    1289             :                                                DewPointTemp,
    1290             :                                                _,
    1291             :                                                "C",
    1292             :                                                "C");
    1293             :             }
    1294             : 
    1295        3386 :         } else if (this->CondCtrlType == CondCtrl::VARIEDOFF) {
    1296             :             // Varied off is the most complex because it tries to run by reducing the inlet temperature
    1297             :             // As a result of this, there is some bypass/recirculation that has to take place.
    1298             :             // We might not have enough flow rate to meet whatever load we have, but at least
    1299             :             // the system is still running at some partial load and avoiding condensation.
    1300        3386 :             waterInletTemp = DewPointTemp + this->CondDewPtDeltaT;
    1301        3386 :             ModifiedWaterInletTemp = true;
    1302             :         }
    1303             :     }
    1304             : 
    1305             :     // The next IF block is to find the mass flow rate based on what type of control the user has requested.  Load based controls
    1306             :     // vary the flow to meet the zone load calculated by the user-defined thermostat.  Temperature based controls vary the flow
    1307             :     // based on a comparison between the control temperature and the setpoint schedule and throttling range.
    1308             : 
    1309       22551 :     if ((this->controlType == ClgPanelCtrlType::ZoneTotalLoad) || (this->controlType == ClgPanelCtrlType::ZoneConvectiveLoad)) {
    1310             : 
    1311       10646 :         if (QZnReq < -SmallLoad && !state.dataZoneEnergyDemand->CurDeadBandOrSetback(ZoneNum) && (CoolingPanelOn)) {
    1312             : 
    1313        2176 :             Cp = GetSpecificHeatGlycol(state,
    1314        1088 :                                        state.dataPlnt->PlantLoop(this->plantLoc.loopNum).FluidName,
    1315             :                                        waterInletTemp,
    1316        1088 :                                        state.dataPlnt->PlantLoop(this->plantLoc.loopNum).FluidIndex,
    1317             :                                        RoutineName);
    1318             : 
    1319             :             // Find the actual load: this parameter modifies what the response of the system should be.  For total load control, the system tries
    1320             :             // to meet the QZnReq.  For convective load control, the convective output of the device equals QZnReq which means that the load on
    1321             :             // the panel is higher as is its output.  Total load control will miss the setpoint temperature but will likely get there with time.
    1322             :             // Convective load control will hit the setpoint short term better but will result in overcooling in the long run probably.
    1323        1088 :             if (this->controlType == ClgPanelCtrlType::ZoneConvectiveLoad) {
    1324           0 :                 QZnReq = QZnReq / this->FracConvect;
    1325             :             }
    1326             : 
    1327             :             // Now for a small amount of iteration.  Try to find the value of mass flow rate that will come the closest to giving
    1328             :             // the proper value for MCpEpsAct.  Limit iterations to avoid too much time wasting.
    1329        1088 :             MCpEpsAct = QZnReq / (waterInletTemp - Tzone);
    1330        1088 :             MCpEpsLow = 0.0;
    1331        1088 :             MdotLow = 0.0;
    1332        1088 :             MCpEpsHigh = waterMassFlowRateMax * Cp * (1.0 - exp(-this->UA / (waterMassFlowRateMax * Cp)));
    1333        1088 :             MdotHigh = waterMassFlowRateMax;
    1334        1088 :             if (MCpEpsAct <= MCpEpsLow) {
    1335           0 :                 MCpEpsAct = MCpEpsLow;
    1336           0 :                 waterMassFlowRate = 0.0;
    1337           0 :                 state.dataLoopNodes->Node(this->WaterInletNode).MassFlowRate = 0.0;
    1338           0 :                 CoolingPanelOn = false;
    1339        1088 :             } else if (MCpEpsAct >= MCpEpsHigh) {
    1340         540 :                 MCpEpsAct = MCpEpsHigh;
    1341         540 :                 waterMassFlowRate = waterMassFlowRateMax;
    1342         540 :                 state.dataLoopNodes->Node(this->WaterInletNode).MassFlowRate = waterMassFlowRateMax;
    1343             :             } else {
    1344         548 :                 for (iter = 1; iter <= Maxiter; ++iter) {
    1345         548 :                     FracGuess = (MCpEpsAct - MCpEpsLow) / (MCpEpsHigh - MCpEpsLow);
    1346         548 :                     MdotGuess = MdotHigh * FracGuess;
    1347         548 :                     MCpEpsGuess = MdotGuess * Cp * (1.0 - exp(-this->UA / (MdotGuess * Cp)));
    1348         548 :                     if (MCpEpsGuess <= MCpEpsAct) {
    1349           0 :                         MCpEpsLow = MCpEpsGuess;
    1350           0 :                         MdotLow = MdotGuess;
    1351             :                     } else { // MCpEpsGuess > MCpEpsAct
    1352         548 :                         MCpEpsHigh = MCpEpsGuess;
    1353         548 :                         MdotHigh = MdotGuess;
    1354             :                     }
    1355         548 :                     if (((MCpEpsAct - MCpEpsGuess) / MCpEpsAct) <= IterTol) {
    1356         548 :                         waterMassFlowRate = MdotGuess;
    1357         548 :                         state.dataLoopNodes->Node(this->WaterInletNode).MassFlowRate = waterMassFlowRate;
    1358         548 :                         break;
    1359             :                     }
    1360             :                 }
    1361             :             }
    1362             : 
    1363             :         } else {
    1364        4235 :             CoolingPanelOn = false;
    1365             :         }
    1366             : 
    1367             :     } else { // temperature control rather than zone load control
    1368             : 
    1369       17228 :         if (CoolingPanelOn) {
    1370             : 
    1371       17228 :             ControlTemp = this->getCoolingPanelControlTemp(state, ZoneNum);
    1372             : 
    1373       17228 :             SetPointTemp = GetCurrentScheduleValue(state, this->ColdSetptSchedPtr);
    1374       17228 :             OffTempCool = SetPointTemp - 0.5 * this->ColdThrottlRange;
    1375       17228 :             FullOnTempCool = SetPointTemp + 0.5 * this->ColdThrottlRange;
    1376             : 
    1377       17228 :             if (ControlTemp <= OffTempCool) {
    1378       13431 :                 MassFlowFrac = 0.0;
    1379       13431 :                 CoolingPanelOn = false;
    1380        3797 :             } else if (ControlTemp >= FullOnTempCool) {
    1381           0 :                 MassFlowFrac = 1.0;
    1382             :             } else {
    1383        3797 :                 MassFlowFrac = (ControlTemp - OffTempCool) / this->ColdThrottlRange;
    1384        3797 :                 if (MassFlowFrac < MinFrac) MassFlowFrac = MinFrac;
    1385             :             }
    1386             : 
    1387       17228 :             waterMassFlowRate = MassFlowFrac * waterMassFlowRateMax;
    1388             :         }
    1389             :     }
    1390             : 
    1391       22551 :     if (CoolingPanelOn) {
    1392        4885 :         SetComponentFlowRate(state, waterMassFlowRate, this->WaterInletNode, this->WaterOutletNode, this->plantLoc);
    1393        4885 :         if (waterMassFlowRate <= 0.0) CoolingPanelOn = false;
    1394             :     }
    1395             : 
    1396       22551 :     if (CoolingPanelOn) {
    1397             :         // Now simulate the system...
    1398        9764 :         Cp = GetSpecificHeatGlycol(state,
    1399        4882 :                                    state.dataPlnt->PlantLoop(this->plantLoc.loopNum).FluidName,
    1400             :                                    waterInletTemp,
    1401        4882 :                                    state.dataPlnt->PlantLoop(this->plantLoc.loopNum).FluidIndex,
    1402             :                                    RoutineName);
    1403        4882 :         Effectiveness = 1.0 - exp(-this->UA / (waterMassFlowRate * Cp));
    1404        4882 :         if (Effectiveness <= 0.0) {
    1405           0 :             Effectiveness = 0.0;
    1406        4882 :         } else if (Effectiveness >= 1.0) {
    1407          30 :             Effectiveness = 1.0;
    1408             :         }
    1409        4882 :         CoolingPanelCool = (Effectiveness)*waterMassFlowRate * Cp * (waterInletTemp - Tzone);
    1410        4882 :         waterOutletTemp = this->WaterInletTemp - (CoolingPanelCool / (waterMassFlowRate * Cp));
    1411        4882 :         RadHeat = CoolingPanelCool * this->FracRadiant;
    1412        4882 :         state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum).CoolingPanelSource = RadHeat;
    1413             : 
    1414        4882 :         if (this->FracRadiant <= MinFrac) {
    1415           0 :             LoadMet = CoolingPanelCool;
    1416             :         } else {
    1417             : 
    1418             :             // Now, distribute the radiant energy of all systems to the appropriate surfaces, to people, and the air
    1419        4882 :             DistributeCoolingPanelRadGains(state);
    1420             :             // Now "simulate" the system by recalculating the heat balances
    1421        4882 :             HeatBalanceSurfaceManager::CalcHeatBalanceOutsideSurf(state, ZoneNum);
    1422             : 
    1423        4882 :             HeatBalanceSurfaceManager::CalcHeatBalanceInsideSurf(state, ZoneNum);
    1424             : 
    1425             :             // Here an assumption is made regarding radiant heat transfer to people.
    1426             :             // While the radiant heat transfer to people array will be used by the thermal comfort
    1427             :             // routines, the energy transfer to people would get lost from the perspective
    1428             :             // of the heat balance.  So, to avoid this net loss of energy which clearly
    1429             :             // gets added to the zones, we must account for it somehow.  This assumption
    1430             :             // that all energy radiated to people is converted to convective energy is
    1431             :             // not very precise, but at least it conserves energy. The system impact to heat balance
    1432             :             // should include this.
    1433       14646 :             LoadMet = (state.dataHeatBal->Zone(ZoneNum).sumHATsurf(state) - state.dataHeatBal->Zone(ZoneNum).ZeroSourceSumHATsurf) +
    1434        9764 :                       (CoolingPanelCool * this->FracConvect) + (RadHeat * this->FracDistribPerson);
    1435             :         }
    1436        4882 :         this->WaterOutletEnthalpy = this->WaterInletEnthalpy - CoolingPanelCool / waterMassFlowRate;
    1437             : 
    1438             :     } else { // cooling panel off
    1439       17669 :         CapacitanceWater = 0.0;
    1440       17669 :         NTU = 0.0;
    1441       17669 :         Effectiveness = 0.0;
    1442       17669 :         waterOutletTemp = waterInletTemp;
    1443       17669 :         CoolingPanelCool = 0.0;
    1444       17669 :         LoadMet = 0.0;
    1445       17669 :         RadHeat = 0.0;
    1446       17669 :         waterMassFlowRate = 0.0;
    1447       17669 :         this->CoolingPanelSource = 0.0;
    1448       17669 :         this->WaterOutletEnthalpy = this->WaterInletEnthalpy;
    1449             :     }
    1450             : 
    1451       22551 :     this->WaterOutletTemp = waterOutletTemp;
    1452       22551 :     this->WaterMassFlowRate = waterMassFlowRate;
    1453       22551 :     this->TotPower = LoadMet;
    1454       22551 :     this->Power = CoolingPanelCool;
    1455       22551 :     this->ConvPower = CoolingPanelCool - RadHeat;
    1456       22551 :     this->RadPower = RadHeat;
    1457       22551 : }
    1458             : 
    1459       17228 : Real64 CoolingPanelParams::getCoolingPanelControlTemp(EnergyPlusData &state, int const ZoneNum) const
    1460             : {
    1461             : 
    1462             :     // SUBROUTINE INFORMATION:
    1463             :     //       AUTHOR         Rick Strand
    1464             :     //       DATE WRITTEN   July 2016
    1465             : 
    1466             :     // METHODOLOGY EMPLOYED:
    1467             :     // This subroutine sets the control temperature for the simple cooling panel.
    1468             : 
    1469             :     // Using/Aliasing
    1470             : 
    1471       17228 :     switch (this->controlType) {
    1472       17228 :     case ClgPanelCtrlType::MAT: {
    1473       17228 :         return state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).MAT;
    1474             :     } break;
    1475           0 :     case ClgPanelCtrlType::MRT: {
    1476           0 :         return state.dataHeatBal->ZoneMRT(ZoneNum);
    1477             :     } break;
    1478           0 :     case ClgPanelCtrlType::Operative: {
    1479           0 :         return 0.5 * (state.dataZoneTempPredictorCorrector->zoneHeatBalance(ZoneNum).MAT + state.dataHeatBal->ZoneMRT(ZoneNum));
    1480             :     } break;
    1481           0 :     case ClgPanelCtrlType::ODB: {
    1482           0 :         return state.dataHeatBal->Zone(ZoneNum).OutDryBulbTemp;
    1483             :     } break;
    1484           0 :     case ClgPanelCtrlType::OWB: {
    1485           0 :         return state.dataHeatBal->Zone(ZoneNum).OutWetBulbTemp;
    1486             :     } break;
    1487           0 :     default: { // Should never get here
    1488           0 :         assert(false);
    1489             :         return -99990; // Compiler wants a return value for every path, so give an invalid value
    1490             :     } break;
    1491             :     }
    1492             : }
    1493             : 
    1494       22551 : void UpdateCoolingPanel(EnergyPlusData &state, int const CoolingPanelNum)
    1495             : {
    1496             : 
    1497             :     // SUBROUTINE INFORMATION:
    1498             :     //       AUTHOR         Rick Strand
    1499             :     //       DATE WRITTEN   Sept 2014
    1500             :     //                      February 2001
    1501             :     //       MODIFIED       Aug 2007 Daeho Kang (Add the update of radiant source)
    1502             : 
    1503             :     // REFERENCES:
    1504             :     // Existing code for hot water baseboard models (radiant-convective variety)
    1505             : 
    1506             :     // Using/Aliasing
    1507       22551 :     auto &SysTimeElapsed = state.dataHVACGlobal->SysTimeElapsed;
    1508       22551 :     auto &TimeStepSys = state.dataHVACGlobal->TimeStepSys;
    1509       22551 :     auto &ThisCP(state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum));
    1510             : 
    1511             :     // First, update the running average if necessary...
    1512       22551 :     if (ThisCP.LastSysTimeElapsed == SysTimeElapsed) {
    1513       21313 :         ThisCP.CoolingPanelSrcAvg -= ThisCP.LastCoolingPanelSrc * ThisCP.LastTimeStepSys / state.dataGlobal->TimeStepZone;
    1514             :     }
    1515             :     // Update the running average and the "last" values with the current values of the appropriate variables
    1516       22551 :     ThisCP.CoolingPanelSrcAvg += ThisCP.CoolingPanelSource * TimeStepSys / state.dataGlobal->TimeStepZone;
    1517             : 
    1518       22551 :     ThisCP.LastCoolingPanelSrc = ThisCP.CoolingPanelSource;
    1519       22551 :     ThisCP.LastSysTimeElapsed = SysTimeElapsed;
    1520       22551 :     ThisCP.LastTimeStepSys = TimeStepSys;
    1521             : 
    1522       22551 :     int WaterInletNode = ThisCP.WaterInletNode;
    1523       22551 :     int WaterOutletNode = ThisCP.WaterOutletNode;
    1524             : 
    1525       22551 :     auto &ThisInNode(state.dataLoopNodes->Node(WaterInletNode));
    1526       22551 :     auto &ThisOutNode(state.dataLoopNodes->Node(WaterOutletNode));
    1527             : 
    1528             :     // Set the outlet water nodes for the panel
    1529       22551 :     PlantUtilities::SafeCopyPlantNode(state, WaterInletNode, WaterOutletNode);
    1530       22551 :     ThisOutNode.Temp = ThisCP.WaterOutletTemp;
    1531       22551 :     ThisOutNode.Enthalpy = ThisCP.WaterOutletEnthalpy;
    1532       22551 :     ThisInNode.MassFlowRate = ThisCP.WaterMassFlowRate;
    1533       22551 :     ThisOutNode.MassFlowRate = ThisCP.WaterMassFlowRate;
    1534       22551 :     ThisInNode.MassFlowRateMax = ThisCP.WaterMassFlowRateMax;
    1535       22551 :     ThisOutNode.MassFlowRateMax = ThisCP.WaterMassFlowRateMax;
    1536       22551 : }
    1537             : 
    1538     2568313 : void UpdateCoolingPanelSourceValAvg(EnergyPlusData &state,
    1539             :                                     bool &CoolingPanelSysOn) // .TRUE. if the radiant system has run this zone time step
    1540             : {
    1541             : 
    1542             :     // SUBROUTINE INFORMATION:
    1543             :     //       AUTHOR         Rick Strand
    1544             :     //       DATE WRITTEN   Sept 2014
    1545             : 
    1546             :     // PURPOSE OF THIS SUBROUTINE:
    1547             :     // To transfer the average value of the heat source over the entire
    1548             :     // zone time step back to the heat balance routines so that the heat
    1549             :     // balance algorithms can simulate one last time with the average source
    1550             :     // to maintain some reasonable amount of continuity and energy balance
    1551             :     // in the temperature and flux histories.
    1552             : 
    1553             :     // METHODOLOGY EMPLOYED:
    1554             :     // All of the record keeping for the average term is done in the Update
    1555             :     // routine so the only other thing that this subroutine does is check to
    1556             :     // see if the system was even on.  If any average term is non-zero, then
    1557             :     // one or more of the radiant systems was running.
    1558             : 
    1559             :     // REFERENCES:
    1560             :     // Existing code for hot water baseboard models (radiant-convective variety)
    1561             : 
    1562             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1563             :     int CoolingPanelNum; // DO loop counter for surface index
    1564             : 
    1565     2568313 :     CoolingPanelSysOn = false;
    1566             : 
    1567             :     // If this was never allocated, then there are no radiant systems in this input file (just RETURN)
    1568     2568313 :     if (!allocated(state.dataChilledCeilingPanelSimple->CoolingPanel)) return;
    1569             : 
    1570             :     // If it was allocated, then we have to check to see if this was running at all...
    1571       14502 :     for (CoolingPanelNum = 1; CoolingPanelNum <= (int)state.dataChilledCeilingPanelSimple->CoolingPanel.size(); ++CoolingPanelNum) {
    1572        8112 :         if (state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum).CoolingPanelSrcAvg != 0.0) {
    1573        1722 :             CoolingPanelSysOn = true;
    1574        1722 :             break; // DO loop
    1575             :         }
    1576             :     }
    1577             : 
    1578       16224 :     for (auto &cp : state.dataChilledCeilingPanelSimple->CoolingPanel) {
    1579        8112 :         cp.CoolingPanelSource = cp.CoolingPanelSrcAvg;
    1580             :     }
    1581             : 
    1582        8112 :     DistributeCoolingPanelRadGains(state); // CoolingPanelRadSource has been modified so we need to redistribute gains
    1583             : }
    1584             : 
    1585       12994 : void DistributeCoolingPanelRadGains(EnergyPlusData &state)
    1586             : {
    1587             : 
    1588             :     // SUBROUTINE INFORMATION:
    1589             :     //       AUTHOR         Rick Strand
    1590             :     //       DATE WRITTEN   Sept 2014
    1591             : 
    1592             :     // PURPOSE OF THIS SUBROUTINE:
    1593             :     // To distribute the gains from the hot water basebaord heater
    1594             :     // as specified in the user input file.  This includes distribution
    1595             :     // of long wavelength radiant gains to surfaces and "people."
    1596             : 
    1597             :     // METHODOLOGY EMPLOYED:
    1598             :     // We must cycle through all of the radiant systems because each
    1599             :     // surface could feel the effect of more than one radiant system.
    1600             :     // Note that the energy radiated to people is assumed to affect them
    1601             :     // but them it is assumed to be convected to the air.
    1602             : 
    1603             :     // REFERENCES:
    1604             :     // Existing code for hot water baseboard models (radiant-convective variety)
    1605             : 
    1606             :     // Using/Aliasing
    1607             :     using DataHeatBalFanSys::MaxRadHeatFlux;
    1608             : 
    1609             :     // SUBROUTINE PARAMETER DEFINITIONS:
    1610       12994 :     Real64 constexpr SmallestArea(0.001); // Smallest area in meters squared (to avoid a divide by zero)
    1611             : 
    1612             :     // SUBROUTINE LOCAL VARIABLE DECLARATIONS:
    1613             :     int RadSurfNum;           // Counter for surfaces receiving radiation from radiant heater
    1614             :     int CoolingPanelNum;      // Counter for the baseboard
    1615             :     int SurfNum;              // Pointer to the Surface derived type
    1616             :     int ZoneNum;              // Pointer to the Zone derived type
    1617             :     Real64 ThisSurfIntensity; // temporary for W/m2 term for rad on a surface
    1618             : 
    1619             :     // Initialize arrays
    1620       12994 :     state.dataHeatBalFanSys->SurfQCoolingPanel = 0.0;
    1621       12994 :     state.dataHeatBalFanSys->ZoneQCoolingPanelToPerson = 0.0;
    1622             : 
    1623       25988 :     for (CoolingPanelNum = 1; CoolingPanelNum <= (int)state.dataChilledCeilingPanelSimple->CoolingPanel.size(); ++CoolingPanelNum) {
    1624             : 
    1625       12994 :         auto &ThisCP(state.dataChilledCeilingPanelSimple->CoolingPanel(CoolingPanelNum));
    1626             : 
    1627       12994 :         ZoneNum = ThisCP.ZonePtr;
    1628       12994 :         if (ZoneNum <= 0) continue;
    1629       12994 :         state.dataHeatBalFanSys->ZoneQCoolingPanelToPerson(ZoneNum) += ThisCP.CoolingPanelSource * ThisCP.FracDistribPerson;
    1630             : 
    1631       51976 :         for (RadSurfNum = 1; RadSurfNum <= ThisCP.TotSurfToDistrib; ++RadSurfNum) {
    1632       38982 :             SurfNum = ThisCP.SurfacePtr(RadSurfNum);
    1633       38982 :             auto &ThisSurf(state.dataSurface->Surface(SurfNum));
    1634       38982 :             if (ThisSurf.Area > SmallestArea) {
    1635       38982 :                 ThisSurfIntensity = (ThisCP.CoolingPanelSource * ThisCP.FracDistribToSurf(RadSurfNum) / ThisSurf.Area);
    1636       38982 :                 state.dataHeatBalFanSys->SurfQCoolingPanel(SurfNum) += ThisSurfIntensity;
    1637       38982 :                 state.dataHeatBalSurf->AnyRadiantSystems = true;
    1638             :                 // CR 8074, trap for excessive intensity (throws off surface balance )
    1639       38982 :                 if (ThisSurfIntensity > MaxRadHeatFlux) {
    1640           0 :                     ShowSevereError(state, "DistributeCoolingPanelRadGains:  excessive thermal radiation heat flux intensity detected");
    1641           0 :                     ShowContinueError(state, "Surface = " + ThisSurf.Name);
    1642           0 :                     ShowContinueError(state, format("Surface area = {:.3R} [m2]", ThisSurf.Area));
    1643           0 :                     ShowContinueError(state, "Occurs in " + cCMO_CoolingPanel_Simple + " = " + ThisCP.EquipID);
    1644           0 :                     ShowContinueError(state, format("Radiation intensity = {:.2R} [W/m2]", ThisSurfIntensity));
    1645           0 :                     ShowContinueError(state, "Assign a larger surface area or more surfaces in " + cCMO_CoolingPanel_Simple);
    1646           0 :                     ShowFatalError(state, "DistributeCoolingPanelRadGains:  excessive thermal radiation heat flux intensity detected");
    1647             :                 }
    1648             :             } else {
    1649           0 :                 ShowSevereError(state, "DistributeCoolingPanelRadGains:  surface not large enough to receive thermal radiation heat flux");
    1650           0 :                 ShowContinueError(state, "Surface = " + ThisSurf.Name);
    1651           0 :                 ShowContinueError(state, format("Surface area = {:.3R} [m2]", ThisSurf.Area));
    1652           0 :                 ShowContinueError(state, "Occurs in " + cCMO_CoolingPanel_Simple + " = " + ThisCP.EquipID);
    1653           0 :                 ShowContinueError(state, "Assign a larger surface area or more surfaces in " + cCMO_CoolingPanel_Simple);
    1654           0 :                 ShowFatalError(state, "DistributeCoolingPanelRadGains:  surface not large enough to receive thermal radiation heat flux");
    1655             :             }
    1656             :         }
    1657             :     }
    1658       12994 : }
    1659             : 
    1660       22551 : void CoolingPanelParams::ReportCoolingPanel(EnergyPlusData &state)
    1661             : {
    1662             : 
    1663             :     // SUBROUTINE INFORMATION:
    1664             :     //       AUTHOR         Rick Strand
    1665             :     //       DATE WRITTEN   Aug 2014
    1666             : 
    1667             :     // REFERENCES:
    1668             :     // Existing code for hot water baseboard models (radiant-convective variety)
    1669             : 
    1670       22551 :     auto &TimeStepSys = state.dataHVACGlobal->TimeStepSys;
    1671             : 
    1672             :     // All of the power numbers are negative for cooling.  This is because they will have a negative
    1673             :     // or cooling impact on the surfaces/zones.  However, the output variables are noted as cooling.
    1674             :     // So, their sign should be positive if actually cooling and we need to reverse the sign here.
    1675             :     // This should not have an impact on any of the internal variables or the heat balances because
    1676             :     // those use other variables.
    1677       22551 :     this->TotPower = -this->TotPower;
    1678       22551 :     this->Power = -this->Power;
    1679       22551 :     this->ConvPower = -this->ConvPower;
    1680       22551 :     this->RadPower = -this->RadPower;
    1681             : 
    1682       22551 :     this->TotEnergy = this->TotPower * TimeStepSys * DataGlobalConstants::SecInHour;
    1683       22551 :     this->Energy = this->Power * TimeStepSys * DataGlobalConstants::SecInHour;
    1684       22551 :     this->ConvEnergy = this->ConvPower * TimeStepSys * DataGlobalConstants::SecInHour;
    1685       22551 :     this->RadEnergy = this->RadPower * TimeStepSys * DataGlobalConstants::SecInHour;
    1686       22551 : }
    1687             : 
    1688        2313 : } // namespace EnergyPlus::CoolingPanelSimple

Generated by: LCOV version 1.13